From 4900b61684c55e8ca52349d5a2d1ce2ae964912f Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Mon, 10 Feb 2025 11:20:24 +0100 Subject: [PATCH 1/8] fix: set debug mode on every event --- pkg/http/mpv2/middleware.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/http/mpv2/middleware.go b/pkg/http/mpv2/middleware.go index 3ad1bd4..0533c28 100644 --- a/pkg/http/mpv2/middleware.go +++ b/pkg/http/mpv2/middleware.go @@ -66,6 +66,13 @@ func MiddlewareDebugMode(next MiddlewareHandler) MiddlewareHandler { return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { if !payload.DebugMode && session.IsGTMDebug(r) { payload.DebugMode = true + for i, event := range payload.Events { + if value, ok := event.Params.(map[string]any); ok { + value["debug_mode"] = true + event.Params = value + } + payload.Events[i] = event + } } return next(l, w, r, payload) } From 79ce1d81e48bce39a31e96fd49ccbf7d821f13f6 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Mon, 10 Feb 2025 11:32:35 +0100 Subject: [PATCH 2/8] chore: skip mke --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1df0b56..7f44726 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: version: latest args: --timeout=5m - - run: make test + - run: GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -race -json ./... | gotestfmt - uses: coverallsapp/github-action@v2 with: From 69594d99fa1de622d709a5b4c9d032eb3febe3c3 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Mon, 10 Feb 2025 11:45:54 +0100 Subject: [PATCH 3/8] feat: add event session id and number --- pkg/http/mpv2/middleware.go | 18 ++++++++++++++++-- pkg/session/ga.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pkg/http/mpv2/middleware.go b/pkg/http/mpv2/middleware.go index 0533c28..6b57534 100644 --- a/pkg/http/mpv2/middleware.go +++ b/pkg/http/mpv2/middleware.go @@ -38,11 +38,25 @@ func MiddlewareSessionID(measurementID string) Middleware { return func(next MiddlewareHandler) MiddlewareHandler { return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { if payload.SessionID == "" { - value, err := session.ParseGASessionID(r, measurementID) + id, err := session.ParseGASessionID(r, measurementID) if err != nil && !errors.Is(err, http.ErrNoCookie) { return err } - payload.SessionID = value + + number, err := session.ParseGASessionNumber(r, measurementID) + if err != nil && !errors.Is(err, http.ErrNoCookie) { + return err + } + + payload.SessionID = id + for i, event := range payload.Events { + if value, ok := event.Params.(map[string]any); ok { + value["ga_session_id"] = id + value["ga_session_number"] = number + event.Params = value + } + payload.Events[i] = event + } } return next(l, w, r, payload) } diff --git a/pkg/session/ga.go b/pkg/session/ga.go index bf51b7f..f9d4741 100644 --- a/pkg/session/ga.go +++ b/pkg/session/ga.go @@ -38,3 +38,19 @@ func ParseGASessionID(r *http.Request, id string) (string, error) { return parts[2], nil } + +func ParseGASessionNumber(r *http.Request, id string) (string, error) { + cookie, err := r.Cookie("_ga_" + id) + if err != nil { + return "", errors.Wrap(err, "failed to retrieve _ga cookie") + } + + parts := strings.Split(cookie.Value, ".") + + // validate + if !strings.HasPrefix(cookie.Value, "GS1.1") || len(parts) < 4 { + return "", errors.New("invalid _ga cookie value") + } + + return parts[3], nil +} From 8c170e83ad60017037e3a6d71d8346d09f0556a7 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Wed, 12 Feb 2025 09:29:07 +0100 Subject: [PATCH 4/8] fix: remove dump --- pkg/provider/cookiebot/client/mpv2middleware.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/provider/cookiebot/client/mpv2middleware.go b/pkg/provider/cookiebot/client/mpv2middleware.go index 06e2830..21d5ac6 100644 --- a/pkg/provider/cookiebot/client/mpv2middleware.go +++ b/pkg/provider/cookiebot/client/mpv2middleware.go @@ -6,7 +6,6 @@ import ( "net/url" "strings" - "github.com/davecgh/go-spew/spew" "github.com/foomo/sesamy-go/pkg/client" "github.com/foomo/sesamy-go/pkg/encoding/mpv2" "github.com/foomo/sesamy-go/pkg/provider/cookiebot" @@ -39,7 +38,6 @@ func MPv2MiddlewarConsent(l *zap.Logger) client.MPv2Middleware { l.With(zap.Error(err), zap.String("value", data)).Warn("failed to unmarshal cookie bot cookie") return next(r, payload) } - spew.Dump(value) consent := func(b bool) *mpv2.Consent { ret := mpv2.ConsentDenied @@ -58,7 +56,6 @@ func MPv2MiddlewarConsent(l *zap.Logger) client.MPv2Middleware { FunctionalityStorage: consent(value.Necessary), SecurityStorage: consent(value.Necessary), } - spew.Dump(payload) return next(r, payload) } From 12c8d87600513a90bfe1aedab7a397e3c14bdf5b Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Wed, 12 Feb 2025 09:29:27 +0100 Subject: [PATCH 5/8] feat: add engagement time middleware --- pkg/http/mpv2/middleware.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/pkg/http/mpv2/middleware.go b/pkg/http/mpv2/middleware.go index 6b57534..54759f8 100644 --- a/pkg/http/mpv2/middleware.go +++ b/pkg/http/mpv2/middleware.go @@ -151,14 +151,34 @@ func MiddlewareIPOverride(next MiddlewareHandler) MiddlewareHandler { } } +func MiddlewareEngagementTime(next MiddlewareHandler) MiddlewareHandler { + return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { + for i, event := range payload.Events { + if value, ok := event.Params.(map[string]any); ok { + value["engagement_time_msec"] = 100 + payload.Events[i] = event + } + } + return next(l, w, r, payload) + } +} func MiddlewarePageLocation(next MiddlewareHandler) MiddlewareHandler { return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { - if referrer := r.Header.Get("Referer"); referrer != "" { - for i, event := range payload.Events { - if value, ok := event.Params.(map[string]any); ok { - value["page_location"] = referrer - payload.Events[i] = event + pageTitle := r.Header.Get("X-Page-Title") + pageLocation := r.Header.Get("Referer") + pageReferrer := r.Header.Get("X-Page-Referrer") + for i, event := range payload.Events { + if value, ok := event.Params.(map[string]any); ok { + if value["page_title"] == "" && pageTitle != "" { + value["page_title"] = pageTitle } + if value["page_referrer"] == "" && pageReferrer != "" { + value["page_referrer"] = pageReferrer + } + if value["page_location"] == "" && pageLocation != "" { + value["page_location"] = pageLocation + } + payload.Events[i] = event } } return next(l, w, r, payload) From 79e6f674099721e14838e81186213be0483c3223 Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Wed, 12 Feb 2025 09:29:42 +0100 Subject: [PATCH 6/8] refactor: use single --- pkg/encoding/mpv2/userdata.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/encoding/mpv2/userdata.go b/pkg/encoding/mpv2/userdata.go index fd16bc0..660cc1b 100644 --- a/pkg/encoding/mpv2/userdata.go +++ b/pkg/encoding/mpv2/userdata.go @@ -2,7 +2,7 @@ package mpv2 // UserData https://developers.google.com/analytics/devguides/collection/ga4/uid-data type UserData struct { - SHA256EmailAddress []SHA256Hash `json:"sha256_email_address,omitempty"` - SHA256PhoneNumber []SHA256Hash `json:"sha256_phone_number,omitempty"` - Address []UserDataAddress `json:"address,omitempty"` + SHA256EmailAddress SHA256Hash `json:"sha256_email_address,omitempty"` + SHA256PhoneNumber SHA256Hash `json:"sha256_phone_number,omitempty"` + Address UserDataAddress `json:"address,omitempty"` } From 08579227f8c2292a8b74ef4baaaa95954586b49a Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Wed, 12 Feb 2025 10:25:03 +0100 Subject: [PATCH 7/8] fix: set values back --- pkg/http/mpv2/middleware.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/http/mpv2/middleware.go b/pkg/http/mpv2/middleware.go index 54759f8..0d12b9a 100644 --- a/pkg/http/mpv2/middleware.go +++ b/pkg/http/mpv2/middleware.go @@ -122,8 +122,9 @@ func MiddlewareUserAgent(next MiddlewareHandler) MiddlewareHandler { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { value["user_agent"] = userAgent - payload.Events[i] = event + event.Params = value } + payload.Events[i] = event } } return next(l, w, r, payload) @@ -143,8 +144,9 @@ func MiddlewareIPOverride(next MiddlewareHandler) MiddlewareHandler { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { value["ip_override"] = ipOverride - payload.Events[i] = event + event.Params = value } + payload.Events[i] = event } } return next(l, w, r, payload) @@ -156,8 +158,9 @@ func MiddlewareEngagementTime(next MiddlewareHandler) MiddlewareHandler { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { value["engagement_time_msec"] = 100 - payload.Events[i] = event + event.Params = value } + payload.Events[i] = event } return next(l, w, r, payload) } @@ -178,8 +181,9 @@ func MiddlewarePageLocation(next MiddlewareHandler) MiddlewareHandler { if value["page_location"] == "" && pageLocation != "" { value["page_location"] = pageLocation } - payload.Events[i] = event + event.Params = value } + payload.Events[i] = event } return next(l, w, r, payload) } From f4b1a3c77bc1230c1a22553b4024699919f9046f Mon Sep 17 00:00:00 2001 From: Kevin Franklin Kim Date: Wed, 12 Feb 2025 11:37:58 +0100 Subject: [PATCH 8/8] fix: check empty --- pkg/http/mpv2/middleware.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pkg/http/mpv2/middleware.go b/pkg/http/mpv2/middleware.go index 0d12b9a..8fbdddb 100644 --- a/pkg/http/mpv2/middleware.go +++ b/pkg/http/mpv2/middleware.go @@ -80,13 +80,6 @@ func MiddlewareDebugMode(next MiddlewareHandler) MiddlewareHandler { return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { if !payload.DebugMode && session.IsGTMDebug(r) { payload.DebugMode = true - for i, event := range payload.Events { - if value, ok := event.Params.(map[string]any); ok { - value["debug_mode"] = true - event.Params = value - } - payload.Events[i] = event - } } return next(l, w, r, payload) } @@ -121,7 +114,9 @@ func MiddlewareUserAgent(next MiddlewareHandler) MiddlewareHandler { if userAgent := r.Header.Get("User-Agent"); userAgent != "" { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { - value["user_agent"] = userAgent + if value["user_agent"] == nil { + value["user_agent"] = userAgent + } event.Params = value } payload.Events[i] = event @@ -143,7 +138,9 @@ func MiddlewareIPOverride(next MiddlewareHandler) MiddlewareHandler { if ipOverride != "" { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { - value["ip_override"] = ipOverride + if value["ip_override"] == nil { + value["ip_override"] = ipOverride + } event.Params = value } payload.Events[i] = event @@ -157,7 +154,9 @@ func MiddlewareEngagementTime(next MiddlewareHandler) MiddlewareHandler { return func(l *zap.Logger, w http.ResponseWriter, r *http.Request, payload *mpv2.Payload[any]) error { for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { - value["engagement_time_msec"] = 100 + if value["engagement_time_msec"] == nil { + value["engagement_time_msec"] = 100 + } event.Params = value } payload.Events[i] = event @@ -172,13 +171,13 @@ func MiddlewarePageLocation(next MiddlewareHandler) MiddlewareHandler { pageReferrer := r.Header.Get("X-Page-Referrer") for i, event := range payload.Events { if value, ok := event.Params.(map[string]any); ok { - if value["page_title"] == "" && pageTitle != "" { + if value["page_title"] == nil && pageTitle != "" { value["page_title"] = pageTitle } - if value["page_referrer"] == "" && pageReferrer != "" { + if value["page_referrer"] == nil && pageReferrer != "" { value["page_referrer"] = pageReferrer } - if value["page_location"] == "" && pageLocation != "" { + if value["page_location"] == nil && pageLocation != "" { value["page_location"] = pageLocation } event.Params = value