tiny-rdm/backend/services/ga_service.go

111 lines
2.1 KiB
Go

package services
import (
"bytes"
"encoding/json"
"github.com/google/uuid"
"net/http"
"runtime"
"strings"
"sync"
"tinyrdm/backend/storage"
)
// google analytics service
type gaService struct {
measurementID string
secretKey string
clientID string
}
type GaDataItem struct {
ClientID string `json:"client_id"`
Events []GaEventItem `json:"events"`
}
type GaEventItem struct {
Name string `json:"name"`
Params map[string]any `json:"params"`
}
var ga *gaService
var onceGA sync.Once
func GA() *gaService {
if ga == nil {
onceGA.Do(func() {
// get or create an unique user id
st := storage.NewLocalStore("device.txt")
uidByte, err := st.Load()
if err != nil {
uidByte = []byte(strings.ReplaceAll(uuid.NewString(), "-", ""))
st.Store(uidByte)
}
ga = &gaService{
clientID: string(uidByte),
}
})
}
return ga
}
func (a *gaService) SetSecretKey(measurementID, secretKey string) {
a.measurementID = measurementID
a.secretKey = secretKey
}
func (a *gaService) isValid() bool {
return len(a.measurementID) > 0 && len(a.secretKey) > 0
}
func (a *gaService) sendEvent(events ...GaEventItem) error {
body, err := json.Marshal(GaDataItem{
ClientID: a.clientID,
Events: events,
})
if err != nil {
return err
}
//url := "https://www.google-analytics.com/debug/mp/collect"
url := "https://www.google-analytics.com/mp/collect"
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return err
}
q := req.URL.Query()
q.Add("measurement_id", a.measurementID)
q.Add("api_secret", a.secretKey)
req.URL.RawQuery = q.Encode()
response, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
//if dump, err := httputil.DumpResponse(response, true); err == nil {
// log.Println(string(dump))
//}
return nil
}
// Startup sends application startup event
func (a *gaService) Startup(version string) {
if !a.isValid() {
return
}
go a.sendEvent(GaEventItem{
Name: "startup",
Params: map[string]any{
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"version": version,
},
})
}