Skip to content

Commit

Permalink
Merge pull request #86 from foomo/v0.11.0
Browse files Browse the repository at this point in the history
feat: add enable geo resolution
  • Loading branch information
franklinkim authored Feb 12, 2025
2 parents 2416084 + 036c32e commit b677df1
Show file tree
Hide file tree
Showing 24 changed files with 296 additions and 141 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ version: '1.0'

# Whether to redact the visitor ip
redactVisitorIp: true
# Enable region specific settings
# https://developers.google.com/tag-platform/tag-manager/server-side/enable-region-specific-settings
enableGeoResolution: true

# --- Google API settings
googleApi:
Expand Down Expand Up @@ -90,8 +93,6 @@ googleTagManager:
googleTag:
# A tag ID is an identifier that you put on your page to load a given Google tag
tagId: G-PZ5ELRCR31
# Enable debug mode for all user devices
debugMode: false
# Whether a page_view should be sent on initial load
sendPageView: true
# TypeScript settings
Expand Down Expand Up @@ -163,20 +164,20 @@ googleTag:
googleAnalytics:
# Enable provider
enabled: true
# Google GTag.js settings
googleGTag:
# Provision custom client
enabled: true
# Client priority
priority: 10
# Patch ecommerce items
ecommerceItems: true
# Google Consent settings
googleConsent:
# Enable consent mode
enabled: true
# Consent mode name
mode: analytics_storage
# Google GTag.js override settings
googleGTagJSOverride:
# Provision custom client
enabled: true
# Client priority
priority: 10
# Patch ecommerce items
ecommerceItems: true
# Google Tag Manager web container settings
webContainer:
# Contemplate package config for generated events
Expand Down
11 changes: 9 additions & 2 deletions cmd/tagmanager/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
facebookprovider "github.com/foomo/sesamy-cli/pkg/provider/facebook"
googleadsprovider "github.com/foomo/sesamy-cli/pkg/provider/googleads"
googleanalyticsprovider "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics"
googletagprovider "github.com/foomo/sesamy-cli/pkg/provider/googletag"
googletagmanagerprovider "github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
microsoftadsprovider "github.com/foomo/sesamy-cli/pkg/provider/microsoftads"
tracifyprovider "github.com/foomo/sesamy-cli/pkg/provider/tracify"
Expand Down Expand Up @@ -48,15 +49,21 @@ func NewServer(root *cobra.Command) {
return err
}

if pkgcmd.Tag(googletagprovider.Tag, tags) {
if err := googletagprovider.Server(tm, cfg.GoogleTag); err != nil {
return errors.Wrap(err, "failed to provision google tag provider")
}
}

if pkgcmd.Tag(googletagmanagerprovider.Tag, tags) {
if err := googletagmanagerprovider.Server(tm, cfg.GoogleTagManager); err != nil {
if err := googletagmanagerprovider.Server(tm, cfg.GoogleTagManager, cfg.EnableGeoResolution); err != nil {
return errors.Wrap(err, "failed to provision google tag manager")
}
}

if cfg.GoogleAnalytics.Enabled && pkgcmd.Tag(googleanalyticsprovider.Tag, tags) {
l.Info("🅿️ Running provider", "name", googleanalyticsprovider.Name, "tag", googleanalyticsprovider.Tag)
if err := googleanalyticsprovider.Server(tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP); err != nil {
if err := googleanalyticsprovider.Server(tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP, cfg.EnableGeoResolution); err != nil {
return errors.Wrap(err, "failed to provision google analytics")
}
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/tagmanager/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewWeb(root *cobra.Command) {

if pkgcmd.Tag(googletagprovider.Tag, tags) {
if err := googletagprovider.Web(tm, cfg.GoogleTag); err != nil {
return errors.Wrap(err, "failed to provision google provider")
return errors.Wrap(err, "failed to provision google tag provider")
}
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ type Config struct {
Version string `json:"version" yaml:"version" jsonschema:"required"`
// Globally redact visitor ip
RedactVisitorIP bool `json:"redactVisitorIp" yaml:"redactVisitorIp"`
// Enable region specific settings
// https://developers.google.com/tag-platform/tag-manager/server-side/enable-region-specific-settings
EnableGeoResolution bool `json:"enableGeoResolution" yaml:"enableGeoResolution"`
// Google Tag settings
GoogleTag GoogleTag `json:"googleTag" yaml:"googleTag"`
// Google API settings
Expand Down
10 changes: 6 additions & 4 deletions pkg/config/googleanalytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (

type GoogleAnalytics struct {
// Enable provider
Enabled bool `json:"enabled" yaml:"enabled"`
GoogleGTag GoogleGTag `json:"googleGTag" yaml:"googleGTag"`
Enabled bool `json:"enabled" yaml:"enabled"`
// Google Consent settings
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"`
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
// GTag.js override configuration
GoogleGTagJSOverride GoogleAnalyticsGTagJSOverride `json:"googleGTagJSOverride" yaml:"googleGTagJSOverride"`
// Google Tag Manager web container settings
WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"`
// Google Tag Manager server container settings
ServerContainer contemplate.Config `json:"serverContainer" yaml:"serverContainer"`
}
10 changes: 10 additions & 0 deletions pkg/config/googleanalyticsgtagjsoverride.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package config

type GoogleAnalyticsGTagJSOverride struct {
// Enable override
Enabled bool `json:"enabled" yaml:"enabled"`
// Client priority
Priority int64 `json:"priority" yaml:"priority"`
// Allow sending items for non ecommerce events
EcommerceItems bool `json:"ecommerceItems" yaml:"ecommerceItems"`
}
8 changes: 0 additions & 8 deletions pkg/config/googlegtag.go

This file was deleted.

2 changes: 0 additions & 2 deletions pkg/config/googletag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package config
type GoogleTag struct {
// A tag ID is an identifier that you put on your page to load a given Google tag
TagID string `json:"tagId" yaml:"tagId"`
// Enable debug mode for all user devices
DebugMode bool `json:"debugMode" yaml:"debugMode"`
// Whether a page_view should be sent on initial load
SendPageView bool `json:"sendPageView" yaml:"sendPageView"`
// TypeScript settings
Expand Down
35 changes: 28 additions & 7 deletions pkg/provider/googleanalytics/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ import (
"github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/trigger"
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent"
googleconsentvariable "github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
"github.com/foomo/sesamy-cli/pkg/provider/googletag"
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
"github.com/foomo/sesamy-cli/pkg/tagmanager"
serverclient "github.com/foomo/sesamy-cli/pkg/tagmanager/server/client"
servertemplate "github.com/foomo/sesamy-cli/pkg/tagmanager/server/template"
servertransformation "github.com/foomo/sesamy-cli/pkg/tagmanager/server/transformation"
servertrigger "github.com/foomo/sesamy-cli/pkg/tagmanager/server/trigger"
servervariable "github.com/foomo/sesamy-cli/pkg/tagmanager/server/variable"
"github.com/foomo/sesamy-cli/pkg/utils"
"github.com/pkg/errors"
api "google.golang.org/api/tagmanager/v2"
)

func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitorIP bool) error {
func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitorIP, enableGeoResolution bool) error {
{ // create folder
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
return err
Expand All @@ -29,17 +31,28 @@ func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitor

{ // create clients
{
client, err := tm.UpsertClient(serverclient.NewGoogleAnalyticsGA4(NameGoogleAnalyticsGA4Client))
measurementID, err := tm.LookupVariable(googletag.NameGoogleTagMeasurementID)
if err != nil {
return err
}

visitorRegion, err := tm.LookupVariable(googletagmanager.NameGoogleTagManagerVisitorRegion)
if err != nil {
return err
}

client, err := tm.UpsertClient(googleanalyticsclient.NewGoogleAnalyticsGA4(NameGoogleAnalyticsGA4Client, enableGeoResolution, visitorRegion, measurementID))
if err != nil {
return err
}

if _, err = tm.UpsertTrigger(servertrigger.NewClient(NameGoogleAnalyticsGA4ClientTrigger, client)); err != nil {
return err
}
}

{
client, err := tm.UpsertClient(serverclient.NewMeasurementProtocolGA4(NameMeasurementProtocolGA4Client))
client, err := tm.UpsertClient(googleanalyticsclient.NewMeasurementProtocolGA4(NameMeasurementProtocolGA4Client))
if err != nil {
return err
}
Expand All @@ -57,19 +70,27 @@ func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitor
return err
}

_, err = tm.UpsertTransformation(servertransformation.NewMPv2UserData(NameMPv2UserDataTransformation, userDataVariable, client))
debugModeVariable, err := tm.UpsertVariable(servervariable.NewMPv2Data("debug_mode", userDataTemplate))
if err != nil {
return err
}

_, err = tm.UpsertTransformation(servertransformation.NewMPv2UserData(NameMPv2UserDataTransformation, map[string]*api.Variable{
"user_data": userDataVariable,
"debug_mode": debugModeVariable,
}, client))
if err != nil {
return err
}
}

if cfg.GoogleGTag.Enabled {
if cfg.GoogleGTagJSOverride.Enabled {
template, err := tm.UpsertCustomTemplate(googleanalyticstemplate.NewGoogleGTagClient(NameGoogleGTagClientTemplate))
if err != nil {
return err
}

_, err = tm.UpsertClient(googleanalyticsclient.NewGoogleGTag(NameGoogleGTagClient, cfg.GoogleGTag, template))
_, err = tm.UpsertClient(googleanalyticsclient.NewGoogleGTag(NameGoogleGTagClient, cfg.GoogleGTagJSOverride, template))
if err != nil {
return err
}
Expand Down
67 changes: 67 additions & 0 deletions pkg/provider/googleanalytics/server/client/googleanalyticsga4.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package client

import (
"strconv"

"google.golang.org/api/tagmanager/v2"
)

func NewGoogleAnalyticsGA4(name string, enableGeoResolution bool, visitorRegion, measurementID *tagmanager.Variable) *tagmanager.Client {
return &tagmanager.Client{
Name: name,
Parameter: []*tagmanager.Parameter{
{
Key: "activateResponseCompression",
Type: "template",
Value: "true",
},
{
Key: "activateGeoResolution",
Type: "boolean",
Value: strconv.FormatBool(enableGeoResolution),
},
{
Key: "activateGtagSupport",
Type: "boolean",
Value: "true",
},
{
Key: "activateDependencyServing",
Type: "boolean",
Value: "true",
},
{
Key: "activateDefaultPaths",
Type: "boolean",
Value: "true",
},
{
Key: "region",
Type: "template",
Value: "{{" + visitorRegion.Name + "}}",
},
{
Key: "cookieManagement",
Type: "template",
Value: "js",
},
{
Key: "gtagMeasurementIds",
Type: "list",
List: []*tagmanager.Parameter{
{
Type: "map",
Map: []*tagmanager.Parameter{
{
Key: "measurementId",
Type: "template",
Value: "{{" + measurementID.Name + "}}",
},
},
},
},
},
},
Type: "gaaw_client",
}
}
2 changes: 1 addition & 1 deletion pkg/provider/googleanalytics/server/client/googlegtag.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"google.golang.org/api/tagmanager/v2"
)

func NewGoogleGTag(name string, cfg config.GoogleGTag, template *tagmanager.CustomTemplate) *tagmanager.Client {
func NewGoogleGTag(name string, cfg config.GoogleAnalyticsGTagJSOverride, template *tagmanager.CustomTemplate) *tagmanager.Client {
return &tagmanager.Client{
Name: name,
Priority: cfg.Priority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,34 @@ const consentType = data.consentType;
// --- GA4 ---
if (eventData['x-ga-gcs']) {
const gcs = eventData['x-ga-gcs'];
if (eventData['x-ga-gcd']) {
const gcd = eventData['x-ga-gcd'];
const isGranted = function(v) {
return v === 't' || v === 'r' || v === 'n' || v === 'v';
};
switch (consentType) {
case "ad_storage":
return (gcs.substring(2, 3) === "1") ? 'granted' : 'denied';
return isGranted(gcd.substring(2, 3)) ? 'granted' : 'denied';
case "analytics_storage":
return (gcs.substring(3, 4) === "1") ? 'granted' : 'denied';
return isGranted(gcd.substring(4, 5)) ? 'granted' : 'denied';
case "ad_user_data":
return isGranted(gcd.substring(6, 7)) ? 'granted' : 'denied';
case "ad_personalization":
return isGranted(gcd.substring(8, 9)) ? 'granted' : 'denied';
default:
return 'denied';
}
}
if (eventData['x-ga-gcd']) {
const gcd = eventData['x-ga-gcd'];
if (eventData['x-ga-gcs']) {
const gcs = eventData['x-ga-gcs'];
switch (consentType) {
case "ad_storage":
return (gcd.substring(2, 3) === "1") ? 'granted' : 'denied';
return (gcs.substring(2, 3) === "1") ? 'granted' : 'denied';
case "ad_user_data":
return (gcs.substring(2, 3) === "1") ? 'granted' : 'denied';
case "analytics_storage":
return (gcd.substring(3, 4) === "1") ? 'granted' : 'denied';
return (gcs.substring(3, 4) === "1") ? 'granted' : 'denied';
default:
return 'denied';
}
Expand All @@ -88,13 +97,23 @@ if (eventData['x-ga-gcd']) {
let requestBody = getRequestBody();
if (requestBody && getRequestHeader('content-type') === 'application/json') {
requestBody = JSON.parse(requestBody);
if (requestBody._consent) {
if (requestBody.consent) {
const consent = requestBody.consent;
switch (consentType) {
case "ad_storage":
return (consent.ad_storage === "GRANTED") ? 'granted' : 'denied';
return (consent.ad_storage && consent.ad_storage.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "ad_user_data":
return (consent.ad_user_data && consent.ad_user_data.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "ad_personalization":
return (consent.ad_personalization && consent.ad_personalization.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "analytics_storage":
return (consent.analytics_storage === "GRANTED") ? 'granted' : 'denied';
return (consent.analytics_storage && consent.analytics_storage.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "functionality_storage":
return (consent.functionality_storage && consent.functionality_storage.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "personalization_storage":
return (consent.personalization_storage && consent.personalization_storage.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
case "security_storage":
return (consent.security_storage && consent.security_storage.toUpperCase() === "GRANTED") ? 'granted' : 'denied';
default:
return 'denied';
}
Expand Down Expand Up @@ -122,7 +141,7 @@ if (cookiebotCookie !== undefined) {
logToConsole('[FAILURE]', {
eventData: eventData,
request: requestBody,
cookie: cookiebotCookie,
cookiebot: cookiebotCookie,
});
return 'denied';
Expand Down
Loading

0 comments on commit b677df1

Please sign in to comment.