diff --git a/README.md b/README.md index 7a111b1..e216e45 100644 --- a/README.md +++ b/README.md @@ -146,10 +146,19 @@ googleTag: - ViewPromotion - WorkingLead + # --- Google Analytics settings 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 Tag Manager web container settings webContainer: # Contemplate package config for generated events @@ -236,6 +245,24 @@ facebook: - BeginCheckout - GenerateLead - ViewItem + +# --- Emarsys +emarsys: + # Enable provider + enabled: true + # Emarsys merchant id + merchantId: '' + # Name of the event to mark as new page view + newPageViewEvent: ''' + # Google Tag Manager server container settings + serverContainer: + # Contemplate package config for generated events + packages: + - path: github.com/foomo/sesamy-go/pkg/event + types: + - Purchase + - ViewItem + - ViewItemList ``` ## Caveats diff --git a/cmd/tagmanager/server.go b/cmd/tagmanager/server.go index caad57b..8c69560 100644 --- a/cmd/tagmanager/server.go +++ b/cmd/tagmanager/server.go @@ -3,6 +3,7 @@ package tagmanager import ( pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd" conversionlinkerprovider "github.com/foomo/sesamy-cli/pkg/provider/conversionlinker" + emarsysprovider "github.com/foomo/sesamy-cli/pkg/provider/emarsys" 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" @@ -58,40 +59,47 @@ func NewServer(root *cobra.Command) { } if cfg.GoogleAnalytics.Enabled && pkgcmd.Tag(googleanalyticsprovider.Tag, tags) { - l.Info("🅿️ Running provider", "name", googleanalyticsprovider.Name) + l.Info("🅿️ Running provider", "name", googleanalyticsprovider.Name, "tag", googleanalyticsprovider.Tag) if err := googleanalyticsprovider.Server(tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP); err != nil { return errors.Wrap(err, "failed to provision google analytics") } } if cfg.ConversionLinker.Enabled && pkgcmd.Tag(conversionlinkerprovider.Tag, tags) { - l.Info("🅿️ Running provider", "name", conversionlinkerprovider.Name) + l.Info("🅿️ Running provider", "name", conversionlinkerprovider.Name, "tag", conversionlinkerprovider.Tag) if err := conversionlinkerprovider.Server(tm, cfg.ConversionLinker); err != nil { return errors.Wrap(err, "failed to provision conversion linker") } } if cfg.Umami.Enabled && pkgcmd.Tag(umamiprovider.Tag, tags) { - l.Info("🅿️ Running provider", "name", umamiprovider.Name) + l.Info("🅿️ Running provider", "name", umamiprovider.Name, "tag", umamiprovider.Tag) if err := umamiprovider.Server(tm, cfg.Umami); err != nil { return errors.Wrap(err, "failed to provision umammi") } } if cfg.Facebook.Enabled && pkgcmd.Tag(facebookprovider.Tag, tags) { - l.Info("🅿️ Running provider", "name", facebookprovider.Name) + l.Info("🅿️ Running provider", "name", facebookprovider.Name, "tag", facebookprovider.Tag) if err := facebookprovider.Server(l, tm, cfg.Facebook); err != nil { return errors.Wrap(err, "failed to provision facebook") } } if cfg.GoogleAds.Enabled && pkgcmd.Tag(googleadsprovider.Tag, tags) { - l.Info("🅿️ Running provider", "name", googleadsprovider.Name) + l.Info("🅿️ Running provider", "name", googleadsprovider.Name, "tag", googleadsprovider.Tag) if err := googleadsprovider.Server(l, tm, cfg.GoogleAds); err != nil { return errors.Wrap(err, "failed to provision google ads") } } + if cfg.Emarsys.Enabled && pkgcmd.Tag(emarsysprovider.Tag, tags) { + l.Info("🅿️ Running provider", "name", emarsysprovider.Name, "tag", emarsysprovider.Tag) + if err := emarsysprovider.Server(l, tm, cfg.Emarsys); err != nil { + return errors.Wrap(err, "failed to provision emarsys") + } + } + return nil }, } diff --git a/cmd/tagmanager/web.go b/cmd/tagmanager/web.go index edc17de..ba8d042 100644 --- a/cmd/tagmanager/web.go +++ b/cmd/tagmanager/web.go @@ -2,6 +2,7 @@ package tagmanager import ( pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd" + emarsysprovider "github.com/foomo/sesamy-cli/pkg/provider/emarsys" googleanaylticsprovider "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics" googletagprovider "github.com/foomo/sesamy-cli/pkg/provider/googletag" "github.com/foomo/sesamy-cli/pkg/tagmanager" @@ -52,6 +53,12 @@ func NewWeb(root *cobra.Command) { } } + if cfg.Emarsys.Enabled && pkgcmd.Tag(emarsysprovider.Tag, tags) { + if err := emarsysprovider.Web(tm, cfg.Emarsys); err != nil { + return errors.Wrap(err, "failed to provision emarsys tag") + } + } + return nil }, } diff --git a/pkg/code/section.go b/pkg/code/section.go index cf8abc3..334c26b 100644 --- a/pkg/code/section.go +++ b/pkg/code/section.go @@ -11,6 +11,13 @@ type Section struct { Parts []string } +func (s *Section) Sprint(a ...any) { + value := fmt.Sprint(a...) + if !slices.Contains(s.Parts, value) { + s.Parts = append(s.Parts, value) + } +} + func (s *Section) Sprintf(format string, a ...any) { value := fmt.Sprintf(format, a...) if !slices.Contains(s.Parts, value) { diff --git a/pkg/config/config.go b/pkg/config/config.go index 64554b4..5ca11f7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,5 +11,6 @@ type Config struct { GoogleAnalytics GoogleAnalytics `json:"googleAnalytics" yaml:"googleAnalytics"` ConversionLinker ConversionLinker `json:"conversionLinker" yaml:"conversionLinker"` Facebook Facebook `json:"facebook" yaml:"facebook"` + Emarsys Emarsys `json:"emarsys" yaml:"emarsys"` Umami Umami `json:"umami" yaml:"umami"` } diff --git a/pkg/config/emarsys.go b/pkg/config/emarsys.go new file mode 100644 index 0000000..05f7d60 --- /dev/null +++ b/pkg/config/emarsys.go @@ -0,0 +1,13 @@ +package config + +import ( + "github.com/foomo/gocontemplate/pkg/contemplate" +) + +type Emarsys struct { + Enabled bool `json:"enabled" yaml:"enabled"` + MerchantID string `json:"merchantId" yaml:"merchantId"` + NewPageViewEvent string `json:"newPageViewEvent" yaml:"newPageViewEvent"` + WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"` + ServerContainer contemplate.Config `json:"serverContainer" yaml:"serverContainer"` +} diff --git a/pkg/config/googleanalytics.go b/pkg/config/googleanalytics.go index ca5cf43..e1cfab7 100644 --- a/pkg/config/googleanalytics.go +++ b/pkg/config/googleanalytics.go @@ -6,6 +6,7 @@ import ( type GoogleAnalytics struct { Enabled bool `json:"enabled" yaml:"enabled"` + GoogleGTag GoogleGTag `json:"googleGTag" yaml:"googleGTag"` WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"` ServerContainer contemplate.Config `json:"serverContainer" yaml:"serverContainer"` } diff --git a/pkg/config/googlegtag.go b/pkg/config/googlegtag.go new file mode 100644 index 0000000..817104c --- /dev/null +++ b/pkg/config/googlegtag.go @@ -0,0 +1,7 @@ +package config + +type GoogleGTag struct { + Enabled bool `json:"enabled" yaml:"enabled"` + Priority int64 `json:"priority" yaml:"priority"` + EcommerceItems bool `json:"ecommerceItems" yaml:"ecommerceItems"` +} diff --git a/pkg/config/googletag.go b/pkg/config/googletag.go index 5d9b757..a4766b0 100644 --- a/pkg/config/googletag.go +++ b/pkg/config/googletag.go @@ -1,10 +1,8 @@ package config type GoogleTag struct { - TagID string `json:"tagId" yaml:"tagId"` - DebugMode bool `json:"debugMode" yaml:"debugMode"` - SendPageView bool `json:"sendPageView" yaml:"sendPageView"` - // WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"` - // ServerContainer contemplate.Config `json:"serverContainer" yaml:"serverContainer"` - TypeScript TypeScript `json:"typeScript" yaml:"typeScript"` + TagID string `json:"tagId" yaml:"tagId"` + DebugMode bool `json:"debugMode" yaml:"debugMode"` + SendPageView bool `json:"sendPageView" yaml:"sendPageView"` + TypeScript TypeScript `json:"typeScript" yaml:"typeScript"` } diff --git a/pkg/provider/emarsys/constants.go b/pkg/provider/emarsys/constants.go new file mode 100644 index 0000000..42a85db --- /dev/null +++ b/pkg/provider/emarsys/constants.go @@ -0,0 +1,12 @@ +package emarsys + +const ( + Tag = "emarsys" + Name = "Emarsys" + NameMerchantIDConstant = "Emarsys Merchant ID" + NameWebEmarsysInitalizationTag = "Emarsys Initialization" + NameWebEmarsysInitalizationTagTemplate = "Emarsys Initialization" + NameServerEmarsysClient = "Emarsys Initialization" + NameServerEmarsysWebExtendTagTemplate = "Emarsys Web Extend" + NameServerEmarsysInitalizationClientTemplate = "Emarsys Initialization" +) diff --git a/pkg/provider/emarsys/server.go b/pkg/provider/emarsys/server.go new file mode 100644 index 0000000..8735cf4 --- /dev/null +++ b/pkg/provider/emarsys/server.go @@ -0,0 +1,67 @@ +package emarsys + +import ( + "log/slog" + + "github.com/foomo/sesamy-cli/pkg/config" + serverclientx "github.com/foomo/sesamy-cli/pkg/provider/emarsys/server/client" + servertagx "github.com/foomo/sesamy-cli/pkg/provider/emarsys/server/tag" + "github.com/foomo/sesamy-cli/pkg/provider/emarsys/server/template" + "github.com/foomo/sesamy-cli/pkg/provider/googletag" + "github.com/foomo/sesamy-cli/pkg/tagmanager" + commontrigger "github.com/foomo/sesamy-cli/pkg/tagmanager/common/trigger" + commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable" + "github.com/pkg/errors" +) + +func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Emarsys) error { + { // create folder + if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil { + return err + } else { + tm.SetFolderName(folder.Name) + } + } + + { // conversion + merchantID, err := tm.UpsertVariable(commonvariable.NewConstant(NameMerchantIDConstant, cfg.MerchantID)) + if err != nil { + return err + } + + tagTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysWebExtendTag(NameServerEmarsysWebExtendTagTemplate)) + if err != nil { + return err + } + + clientTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysInitializationClient(NameServerEmarsysInitalizationClientTemplate)) + if err != nil { + return err + } + + _, err = tm.UpsertClient(serverclientx.NewEmarsys(NameServerEmarsysClient, cfg, clientTemplate)) + if err != nil { + return err + } + + { // create tags + eventParameters, err := googletag.CreateServerEventTriggers(tm, cfg.ServerContainer) + if err != nil { + return err + } + + for event := range eventParameters { + eventTrigger, err := tm.LookupTrigger(commontrigger.EventName(event)) + if err != nil { + return errors.Wrap(err, "failed to lookup event trigger: "+event) + } + + if _, err := tm.UpsertTag(servertagx.NewEmarsys(event, cfg.NewPageViewEvent == eventTrigger.Name, merchantID, tagTemplate, eventTrigger)); err != nil { + return err + } + } + } + } + + return nil +} diff --git a/pkg/provider/emarsys/server/client/emarsys.go b/pkg/provider/emarsys/server/client/emarsys.go new file mode 100644 index 0000000..5c4a5d7 --- /dev/null +++ b/pkg/provider/emarsys/server/client/emarsys.go @@ -0,0 +1,21 @@ +package client + +import ( + "github.com/foomo/sesamy-cli/pkg/config" + "github.com/foomo/sesamy-cli/pkg/utils" + "google.golang.org/api/tagmanager/v2" +) + +func NewEmarsys(name string, cfg config.Emarsys, template *tagmanager.CustomTemplate) *tagmanager.Client { + return &tagmanager.Client{ + Name: name, + Parameter: []*tagmanager.Parameter{ + { + Key: "merchantId", + Type: "template", + Value: cfg.MerchantID, + }, + }, + Type: utils.TemplateType(template), + } +} diff --git a/pkg/provider/emarsys/server/tag/emarsys.go b/pkg/provider/emarsys/server/tag/emarsys.go new file mode 100644 index 0000000..6af54aa --- /dev/null +++ b/pkg/provider/emarsys/server/tag/emarsys.go @@ -0,0 +1,48 @@ +package tag + +import ( + "strconv" + + "github.com/foomo/sesamy-cli/pkg/utils" + "google.golang.org/api/tagmanager/v2" +) + +func EmarsysName(v string) string { + return "Emarsys - " + v +} + +func NewEmarsys(name string, isNewPageView bool, merchantID *tagmanager.Variable, template *tagmanager.CustomTemplate, triggers ...*tagmanager.Trigger) *tagmanager.Tag { + return &tagmanager.Tag{ + FiringTriggerId: utils.TriggerIDs(triggers), + Name: EmarsysName(name), + TagFiringOption: "oncePerEvent", + Parameter: []*tagmanager.Parameter{ + { + Key: "adStorageConsent", + Type: "template", + Value: "optional", + }, + { + Key: "isNewPageView", + Type: "boolean", + Value: strconv.FormatBool(isNewPageView), + }, + { + Key: "merchantId", + Type: "template", + Value: "{{" + merchantID.Name + "}}", + }, + { + Key: "isTestMode", + Type: "boolean", + Value: "false", + }, + { + Key: "isDebugMode", + Type: "boolean", + Value: "false", + }, + }, + Type: utils.TemplateType(template), + } +} diff --git a/pkg/provider/emarsys/server/template/emarsysinitalizationclient.go b/pkg/provider/emarsys/server/template/emarsysinitalizationclient.go new file mode 100644 index 0000000..664a879 --- /dev/null +++ b/pkg/provider/emarsys/server/template/emarsysinitalizationclient.go @@ -0,0 +1,14 @@ +package template + +import ( + "fmt" + + "google.golang.org/api/tagmanager/v2" +) + +func NewEmarsysInitializationClient(name string) *tagmanager.CustomTemplate { + return &tagmanager.CustomTemplate{ + Name: name, + TemplateData: fmt.Sprintf(EmarsysInitializationClientData, name), + } +} diff --git a/pkg/provider/emarsys/server/template/emarsysinitializationclientdata.go b/pkg/provider/emarsys/server/template/emarsysinitializationclientdata.go new file mode 100644 index 0000000..ff76deb --- /dev/null +++ b/pkg/provider/emarsys/server/template/emarsysinitializationclientdata.go @@ -0,0 +1,410 @@ +package template + +const EmarsysInitializationClientData = `___INFO___ + +{ + "type": "CLIENT", + "id": "cvt_temp_public_id", + "version": 1, + "securityGroups": [], + "displayName": "%s", + "brand": { + "id": "brand_dummy", + "displayName": "sesamy", + "thumbnail": "data:image/jpeg;base64,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qEqaLUwCNxCKZYOe6dFBjPqDoI4rERBIeBK+DcwoAKKtaCJQ+CDXNNpzqBHmCcxwpoi4JJrgyjGuyUw6hlELaeQAclgnHgpfqegeEYRvPCCZjzpIAMAApp7QIXKDg64ETjEUywYBJYAumw8qf4osOWJtRl7cG9iVlHm/IhbCBrmm1OVtwJeMRXJRLxhNIBbVpW3vsRC55EpIAAwDDWJW3uAEmAJNAms8qaYiOYa3K29p8ErIiKQyBXJtclbewbjEVyUUZ0EAmcAoBr8rb1Mx3SRQfE/EwEB9BlbfkgwSaBRY/cs0eR9ElbU5iWRDFn+JoAwvoyOUwaKCYioAIf8ATf8A/9oADAMAAAERAhEAABDzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzglbrzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzilRuyvzzzzzzzzzzzzzzzzzzzzzzzzzzzzywTezzzyvzzzzzzzzzzzzzzzzzzzzzzzzzzywcRbzzzzyvzzzzzzzzzzzzzzzzzzzzzzzzzRDVzzzzzzzyvzzzzzzzzzzzzzzzzzzzzzzgl913zzzzzzzU8fzzzzzzzzzzzzzzzzzzzziUdyzzzzzzzzr1wzzzzzzzzzzzzzzzzzzzywP27zzzzzzzzGO0zzzzzzzzzzzzzzzzzzzgQzZ/zzzzzzznNqwzzzzzzzzzzzzzzzzzzzzh033zzzzzz3PHozzzzzzg4vzzzzzzzzzzzzzyy/zzzzzzzG3wxzzzzzg0zIPzzzzzzzzzzzzzzz/wA88845TNc888884JwSCCD888888888888888/889hL7K08888ymiACCCCD888888888888888/+sqE8ss4GuAHhACCCCCCD888888888888884jG088888utswCCCCCCCCCI888888888888888sY+z+8888+9CCCCCCELLuM88888888888888888sdFiU8888CCCCEJqMc888888888888888888888sc2P188CCFPlcc88888888888888888888888888Mqw4GItO8888882888888888888888888888888sdsM88888oirj88888888888888888888888888888880BqCAq888888888888888888888888888880XSgAAAq888888888888888888888888884rNjACAAAAq888888888888888888888888ompLAAAAAAAEC88888888888888888888882QxiiCAAAAAD+Tc88888888888888888888sJEAAAAAAACbExM8888888888888888888884VAAAAAAAIFU/sc8888888888888888888888oVAAAACABIMM8888888888888888888888888oVAACXbks8888888888888888888888888888oVANEtM8888888888888888888888888888884QePc888888888888888888888888888888888cs8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888//EACMRAQACAgEEAwEBAQAAAAAAAAEAESExQBAgMFBBUXFwYYH/2gAIAQIRAT8Q/hWOW2VHoYC1mKzY9V0dNXPOtVMALiOfZq5oluo7gRO10rs1cveMzG4kRXl6ALRbMSZZjjBLdyu9XG4ZlwBo4xtqYIXGsvANzWMf7MhmwBRxhbdT4T/2OW/ACuJm8CZurZRxtkzMXgR21fgZoJlsIVhx8RtMeYIqtvgdo3PncNo8nT+eDVMTN5QWh4AYSATfgafztBdTIVRM25YAYPAJh9oAdd+Bp/OodJlmOibhagSzvEwkK7d+Bp/IpREcxjQ7EWIpGteo2BPBvwKafiqXfdcGooKAeFBFbfBQ7huY35L7tHfcSRbxUHc1mO79Hcginl/pIiOemjqgj9Iq87exTMINxBH6Rb9Eg+FBufCRLZ9CMI6i301c8SK9urmIIBqL3tXKST4SKd+DMFcgBEdRz4AXUR3B4y6gkV4RM+yAa5D8JIA3Ar0IrBPQgLqI7gnoQTPsgDXoUFQDcAP4N//EACMRAQACAgEDBQEBAAAAAAAAAAEAESExQCAwQRBQUWGhcIH/2gAIAQERAT8Q/hSCKy/YgIj6aOfZBNRT0aOagnhIq9WjlpIviLfY1ckSKeyJg+YAcbEEiPZGwDcMcZQnwxTvsowJ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" + }, + "description": "Managed by Sesamy. DO NOT EDIT.\nSend events to Emarsys", + "containerContexts": [ + "SERVER" + ] +} + + +___TEMPLATE_PARAMETERS___ + +[ + { + "type": "TEXT", + "name": "merchantId", + "displayName": "", + "simpleValueType": true + } +] + + +___SANDBOXED_JS_FOR_SERVER___ + +const JSON = require('JSON'); +const sendHttpGet = require('sendHttpGet'); +const claimRequest = require('claimRequest'); +const logToConsole = require('logToConsole'); +const getRequestPath = require('getRequestPath'); +const getRequestHeader = require('getRequestHeader'); +const setResponseStatus = require('setResponseStatus'); +const setResponseHeader = require('setResponseHeader'); +const getRequestQueryParameter = require('getRequestQueryParameter'); +const encodeUriComponent = require('encodeUriComponent'); +const setResponseBody = require('setResponseBody'); +const getCookieValues = require('getCookieValues'); +const returnResponse = require('returnResponse'); +const setCookie = require('setCookie'); + +// --- Validation --- + +if (getRequestPath() !== '/gtag/js/emarsys') { + return; +} + +claimRequest(); + +const sessionId = getCookieValues('emarsys_s')[0] || getRequestQueryParameter('s'); +const visitorId = getCookieValues('emarsys_cdv')[0] || getRequestQueryParameter('vi'); +const pageViewId = getRequestQueryParameter('pv') || null; + +if (!pageViewId || !sessionId || !visitorId) { + setResponseStatus(400); + returnResponse(); + return; +} + +// --- Config --- + +const merchantUrl = 'https://recommender.scarabresearch.com/merchants/'+data.merchantId+'/&'; + +// --- Main --- + +const headers = { + 'host': getRequestHeader('host'), + 'referer': getRequestHeader('referer'), + 'user-agent': getRequestHeader('user-agent'), +}; + +let query = ['xp=1', 'cp=1']; +if (sessionId) query.push('s='+encodeUriComponent(sessionId)); +if (visitorId) query.push('vi='+encodeUriComponent(visitorId)); +if (pageViewId) query.push('pv='+encodeUriComponent(pageViewId)); + +logToConsole(JSON.stringify({ + url: merchantUrl, + query: query, + headers: headers, +})); + +// send empty request to receive session information +sendHttpGet(merchantUrl+'?'+query.join('&'), {headers: headers, timeout: 500}).then((result) => { + setResponseBody(result.body); + setResponseHeaders(result.headers); + setResponseStatus(result.statusCode); + returnResponse(); +}); + +// --- Utils --- + +function setResponseHeaders(headers) { + for (const key in headers) { + if (key === "set-cookie") { + setResponseCookies(headers[key]); + } else { + setResponseHeader(key, headers[key]); + } + } +} + +function setResponseCookies(setCookieHeader) { + for (let i = 0; i < setCookieHeader.length; i++) { + const setCookieArray = setCookieHeader[i].split("; ").map((pair) => pair.split("=")); + let setCookieJson = ""; + for (let j = 1; j < setCookieArray.length; j++) { + if (j === 1) setCookieJson += "{"; + if (setCookieArray[j].length > 1) setCookieJson += '"' + setCookieArray[j][0] + '": "' + setCookieArray[j][1] + '"'; + else setCookieJson += '"' + setCookieArray[j][0] + '": ' + true; + if (j + 1 < setCookieArray.length) setCookieJson += ","; + else setCookieJson += "}"; + } + const cookieJson = JSON.parse(setCookieJson); + cookieJson.path = "/"; + setCookie("emarsys_"+setCookieArray[0][0], setCookieArray[0][1], cookieJson); + } +} + + +___SERVER_PERMISSIONS___ + +[ + { + "instance": { + "key": { + "publicId": "read_request", + "versionId": "1" + }, + "param": [ + { + "key": "requestAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "headerAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "queryParameterAccess", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "logging", + "versionId": "1" + }, + "param": [ + { + "key": "environments", + "value": { + "type": 1, + "string": "debug" + } + } + ] + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "send_http", + "versionId": "1" + }, + "param": [ + { + "key": "allowedUrls", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "access_response", + "versionId": "1" + }, + "param": [ + { + "key": "writeResponseAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "writeHeaderAccess", + "value": { + "type": 1, + "string": "specific" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "return_response", + "versionId": "1" + }, + "param": [] + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "set_cookies", + "versionId": "1" + }, + "param": [ + { + "key": "allowedCookies", + "value": { + "type": 2, + "listItem": [ + { + "type": 3, + "mapKey": [ + { + "type": 1, + "string": "name" + }, + { + "type": 1, + "string": "domain" + }, + { + "type": 1, + "string": "path" + }, + { + "type": 1, + "string": "secure" + }, + { + "type": 1, + "string": "session" + } + ], + "mapValue": [ + { + "type": 1, + "string": "emarsys_cdv" + }, + { + "type": 1, + "string": "*" + }, + { + "type": 1, + "string": "*" + }, + { + "type": 1, + "string": "secure" + }, + { + "type": 1, + "string": "non_session" + } + ] + }, + { + "type": 3, + "mapKey": [ + { + "type": 1, + "string": "name" + }, + { + "type": 1, + "string": "domain" + }, + { + "type": 1, + "string": "path" + }, + { + "type": 1, + "string": "secure" + }, + { + "type": 1, + "string": "session" + } + ], + "mapValue": [ + { + "type": 1, + "string": "emarsys_s" + }, + { + "type": 1, + "string": "*" + }, + { + "type": 1, + "string": "*" + }, + { + "type": 1, + "string": "secure" + }, + { + "type": 1, + "string": "session" + } + ] + } + ] + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "get_cookies", + "versionId": "1" + }, + "param": [ + { + "key": "cookieAccess", + "value": { + "type": 1, + "string": "specific" + } + }, + { + "key": "cookieNames", + "value": { + "type": 2, + "listItem": [ + { + "type": 1, + "string": "emarsys_s" + }, + { + "type": 1, + "string": "emarsys_cdv" + } + ] + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + } +] + + +___TESTS___ + +scenarios: [] + + +___NOTES___ + +Code generated by sesamy. DO NOT EDIT. +` diff --git a/pkg/provider/emarsys/server/template/emarsyswebextendtag.go b/pkg/provider/emarsys/server/template/emarsyswebextendtag.go new file mode 100644 index 0000000..081ee11 --- /dev/null +++ b/pkg/provider/emarsys/server/template/emarsyswebextendtag.go @@ -0,0 +1,14 @@ +package template + +import ( + "fmt" + + "google.golang.org/api/tagmanager/v2" +) + +func NewEmarsysWebExtendTag(name string) *tagmanager.CustomTemplate { + return &tagmanager.CustomTemplate{ + Name: name, + TemplateData: fmt.Sprintf(EmarsysWebExtendTagData, name), + } +} diff --git a/pkg/provider/emarsys/server/template/emarsyswebextendtagdata.go b/pkg/provider/emarsys/server/template/emarsyswebextendtagdata.go new file mode 100644 index 0000000..9067a28 --- /dev/null +++ b/pkg/provider/emarsys/server/template/emarsyswebextendtagdata.go @@ -0,0 +1,430 @@ +package template + +const EmarsysWebExtendTagData = `___INFO___ + +{ + "type": "TAG", + "id": "cvt_temp_public_id", + "version": 1, + "securityGroups": [], + "displayName": "%s", + "brand": { + "id": "brand_dummy", + "displayName": "sesamy", + "thumbnail": "data:image/jpeg;base64,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qEqaLUwCNxCKZYOe6dFBjPqDoI4rERBIeBK+DcwoAKKtaCJQ+CDXNNpzqBHmCcxwpoi4JJrgyjGuyUw6hlELaeQAclgnHgpfqegeEYRvPCCZjzpIAMAApp7QIXKDg64ETjEUywYBJYAumw8qf4osOWJtRl7cG9iVlHm/IhbCBrmm1OVtwJeMRXJRLxhNIBbVpW3vsRC55EpIAAwDDWJW3uAEmAJNAms8qaYiOYa3K29p8ErIiKQyBXJtclbewbjEVyUUZ0EAmcAoBr8rb1Mx3SRQfE/EwEB9BlbfkgwSaBRY/cs0eR9ElbU5iWRDFn+JoAwvoyOUwaKCYioAIf8ATf8A/9oADAMAAAERAhEAABDzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzglbrzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzilRuyvzzzzzzzzzzzzzzzzzzzzzzzzzzzzywTezzzyvzzzzzzzzzzzzzzzzzzzzzzzzzzywcRbzzzzyvzzzzzzzzzzzzzzzzzzzzzzzzzRDVzzzzzzzyvzzzzzzzzzzzzzzzzzzzzzzgl913zzzzzzzU8fzzzzzzzzzzzzzzzzzzzziUdyzzzzzzzzr1wzzzzzzzzzzzzzzzzzzzywP27zzzzzzzzGO0zzzzzzzzzzzzzzzzzzzgQzZ/zzzzzzznNqwzzzzzzzzzzzzzzzzzzzzh033zzzzzz3PHozzzzzzg4vzzzzzzzzzzzzzyy/zzzzzzzG3wxzzzzzg0zIPzzzzzzzzzzzzzzz/wA88845TNc888884JwSCCD888888888888888/889hL7K08888ymiACCCCD888888888888888/+sqE8ss4GuAHhACCCCCCD888888888888884jG088888utswCCCCCCCCCI888888888888888sY+z+8888+9CCCCCCELLuM88888888888888888sdFiU8888CCCCEJqMc888888888888888888888sc2P188CCFPlcc88888888888888888888888888Mqw4GItO8888882888888888888888888888888sdsM88888oirj88888888888888888888888888888880BqCAq888888888888888888888888888880XSgAAAq888888888888888888888888884rNjACAAAAq888888888888888888888888ompLAAAAAAAEC88888888888888888888882QxiiCAAAAAD+Tc88888888888888888888sJEAAAAAAACbExM8888888888888888888884VAAAAAAAIFU/sc8888888888888888888888oVAAAACABIMM8888888888888888888888888oVAACXbks8888888888888888888888888888oVANEtM8888888888888888888888888888884QePc888888888888888888888888888888888cs8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888//EACMRAQACAgEEAwEBAQAAAAAAAAEAESExQBAgMFBBUXFwYYH/2gAIAQIRAT8Q/hWOW2VHoYC1mKzY9V0dNXPOtVMALiOfZq5oluo7gRO10rs1cveMzG4kRXl6ALRbMSZZjjBLdyu9XG4ZlwBo4xtqYIXGsvANzWMf7MhmwBRxhbdT4T/2OW/ACuJm8CZurZRxtkzMXgR21fgZoJlsIVhx8RtMeYIqtvgdo3PncNo8nT+eDVMTN5QWh4AYSATfgafztBdTIVRM25YAYPAJh9oAdd+Bp/OodJlmOibhagSzvEwkK7d+Bp/IpREcxjQ7EWIpGteo2BPBvwKafiqXfdcGooKAeFBFbfBQ7huY35L7tHfcSRbxUHc1mO79Hcginl/pIiOemjqgj9Iq87exTMINxBH6Rb9Eg+FBufCRLZ9CMI6i301c8SK9urmIIBqL3tXKST4SKd+DMFcgBEdRz4AXUR3B4y6gkV4RM+yAa5D8JIA3Ar0IrBPQgLqI7gnoQTPsgDXoUFQDcAP4N//EACMRAQACAgEDBQEBAAAAAAAAAAEAESExQCAwQRBQUWGhcIH/2gAIAQERAT8Q/hSCKy/YgIj6aOfZBNRT0aOagnhIq9WjlpIviLfY1ckSKeyJg+YAcbEEiPZGwDcMcZQnwxTvsowJ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" + }, + "description": "Managed by Sesamy. DO NOT EDIT.\nSend events to Emarsys", + "containerContexts": [ + "SERVER" + ] +} + + +___TEMPLATE_PARAMETERS___ + +[ + { + "type": "TEXT", + "name": "merchantId", + "displayName": "Merchant ID", + "simpleValueType": true + }, + { + "type": "CHECKBOX", + "name": "isNewPageView", + "checkboxText": "New Page View", + "simpleValueType": true + }, + { + "type": "GROUP", + "name": "consentSettingsGroup", + "displayName": "Consent Settings", + "groupStyle": "ZIPPY_CLOSED", + "subParams": [ + { + "type": "RADIO", + "name": "adStorageConsent", + "displayName": "", + "radioItems": [ + { + "value": "optional", + "displayValue": "Send data always" + }, + { + "value": "required", + "displayValue": "Send data in case marketing consent given" + } + ], + "simpleValueType": true, + "defaultValue": "optional" + } + ] + }, + { + "type": "GROUP", + "name": "debugSettingsGroup", + "displayName": "Debug Settings", + "groupStyle": "ZIPPY_CLOSED", + "subParams": [ + { + "type": "CHECKBOX", + "name": "isTestMode", + "checkboxText": "Test Mode", + "simpleValueType": true + }, + { + "type": "CHECKBOX", + "name": "isDebugMode", + "checkboxText": "Debug Mode", + "simpleValueType": true + } + ] + } +] + + +___SANDBOXED_JS_FOR_SERVER___ + +const Math = require('Math'); +const JSON = require('JSON'); +const sendHttpGet = require('sendHttpGet'); +const setResponseBody = require('setResponseBody'); +const setResponseStatus = require('setResponseStatus'); +const encodeUriComponent = require('encodeUriComponent'); +const getAllEventData = require('getAllEventData'); +const getRequestHeader = require('getRequestHeader'); +const getCookieValues = require('getCookieValues'); +const generateRandom = require('generateRandom'); +const logToConsole = require('logToConsole'); + +// --- Config --- + +const eventData = getAllEventData(); +const merchantUrl = 'https://recommender.scarabresearch.com/merchants/'+data.merchantId+'/'; + +// --- Consent --- + +if (!isConsentGivenOrNotRequired()) { + return data.gtmOnSuccess(); +} + +// --- Main --- + +const mappedData = mapEventData(); +logToConsole(JSON.stringify(mappedData)); + +return sendHttpGet(merchantUrl+'?'+serializeData(mappedData)).then((result) => { + if (result.statusCode >= 200 && result.statusCode < 300) { + setResponseBody(result.body); + data.gtmOnSuccess(); + } else { + data.gtmOnFailure(); + } + setResponseStatus(result.statusCode); +}); + +// --- Utils --- + +function mapEventData() { + const mappedData = { + customerId: eventData.user_id || null, + sessionId: getCookieValues('emarsys_s')[0] || eventData.ga_session_id, + pageViewId: eventData.page_view_id || generatePageViewId(), + isNewPageView: eventData.event_name == 'custom', + visitorId: getCookieValues('emarsys_cdv')[0] || eventData.client_id, + referrer: eventData.page_referrer || null, + orderId: null, + order: null, + category: null, + view: null, + cart: null, + }; + + switch (eventData.event_name) { + // custom events + case 'emarsys_cart': { + mappedData.cart = serializeItems(eventData.items || []); + break; + } + case 'emarsys_category': { + mappedData.category = eventData.item_list_name; + break; + } + case 'emarsys_purchase': { + mappedData.orderId = eventData.transaction_id; + mappedData.order = serializeItems(eventData.items || []); + break; + } + case 'emarsys_view': { + mappedData.view = serializeItem(eventData.items[0] || {}); + break; + } + // standard ecommerce evens + case 'view_cart': { + mappedData.cart = serializeItems(eventData.items || []); + break; + } + case 'view_item_list': { + mappedData.category = eventData.item_list_name; + break; + } + case 'purchase': { + mappedData.orderId = eventData.transaction_id; + mappedData.order = serializeItems(eventData.items || []); + break; + } + case 'view_item': { + mappedData.view = serializeItem(eventData.items[0] || {}); + break; + } + } + return mappedData; +} + +function serializeItems(items) { + const ret = []; + items.forEach((item) => { + ret.push(serializeItem(item)); + }); + return ret.join('|'); +} + +function serializeItem(item) { + const ret = []; + if (item.item_id) { + ret.push('i:'+item.item_id); + } + if (item.price) { + ret.push('p:'+item.price); + } + if (item.quantity) { + ret.push('q:'+item.quantity); + } + return ret.join(','); +} + +function serializeData(mappedData) { + const slist = []; + + slist.push("cp=1"); + slist.push("pv=" + mappedData.pageViewId); + + if (mappedData.isNewPageView) { + slist.push("xp=1"); + } + if (mappedData.customerId) { + slist.push("ci=" + encodeUriComponent(mappedData.customId)); + } + if (mappedData.sessionId) { + slist.push("s=" + encodeUriComponent(mappedData.sessionId)); + } + if (mappedData.visitorId) { + slist.push("vi=" + encodeUriComponent(mappedData.visitorId)); + } + if (mappedData.category) { + slist.push("vc=" + encodeUriComponent(mappedData.category)); + } + if (mappedData.view) { + slist.push("v=" + encodeUriComponent(mappedData.view)); + } + if (mappedData.orderId) { + slist.push("oi=" + encodeUriComponent(mappedData.orderId)); + } + if (mappedData.order) { + slist.push("co=" + encodeUriComponent(mappedData.order)); + } + if (mappedData.cart) { + slist.push("ca=" + encodeUriComponent(mappedData.cart)); + slist.push("cv=1"); + } + if (mappedData.referrer) { + slist.push("prev_url=" + encodeUriComponent(mappedData.referrer)); + } + if (data.isTestMode) { + slist.push("test=true"); + } + if (data.isDebugMode) { + slist.push("debug=true"); + } + logToConsole(JSON.stringify(slist)); + return slist.join("&"); +} + +function generatePageViewId() { + return generateRandom(0, Math.pow(2, 31)); +} + +function isConsentGivenOrNotRequired() { + if (data.adStorageConsent !== 'required') { + return true; + } + if (eventData.consent_state) { + return !!eventData.consent_state.ad_storage; + } + const xGaGcs = eventData['x-ga-gcs'] || ''; // x-ga-gcs is a string like "G110" + return xGaGcs[2] === '1'; +} + + +___SERVER_PERMISSIONS___ + +[ + { + "instance": { + "key": { + "publicId": "read_request", + "versionId": "1" + }, + "param": [ + { + "key": "requestAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "headerAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "queryParameterAccess", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "get_cookies", + "versionId": "1" + }, + "param": [ + { + "key": "cookieAccess", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "read_event_data", + "versionId": "1" + }, + "param": [ + { + "key": "eventDataAccess", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "access_response", + "versionId": "1" + }, + "param": [ + { + "key": "writeResponseAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "writeHeaderAccess", + "value": { + "type": 1, + "string": "specific" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "send_http", + "versionId": "1" + }, + "param": [ + { + "key": "allowedUrls", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "logging", + "versionId": "1" + }, + "param": [ + { + "key": "environments", + "value": { + "type": 1, + "string": "debug" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + } +] + + +___TESTS___ + +scenarios: [] + + +___NOTES___ + +Code generated by sesamy. DO NOT EDIT. +` diff --git a/pkg/provider/emarsys/web.go b/pkg/provider/emarsys/web.go new file mode 100644 index 0000000..80b97f6 --- /dev/null +++ b/pkg/provider/emarsys/web.go @@ -0,0 +1,64 @@ +package emarsys + +import ( + "github.com/foomo/sesamy-cli/pkg/config" + "github.com/foomo/sesamy-cli/pkg/provider/emarsys/web/tag" + "github.com/foomo/sesamy-cli/pkg/provider/emarsys/web/template" + containertag "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/web/tag" + "github.com/foomo/sesamy-cli/pkg/provider/googletag" + commonvariable "github.com/foomo/sesamy-cli/pkg/provider/googletag/web/variable" + "github.com/foomo/sesamy-cli/pkg/tagmanager" + commontrigger "github.com/foomo/sesamy-cli/pkg/tagmanager/common/trigger" + "github.com/pkg/errors" +) + +func Web(tm *tagmanager.TagManager, cfg config.Emarsys) error { + { // create folder + if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil { + return err + } else { + tm.SetFolderName(folder.Name) + } + } + + { // create initialization tag + tagTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysInitializationTag(NameWebEmarsysInitalizationTagTemplate)) + if err != nil { + return err + } + + if _, err = tm.UpsertTag(tag.NewEmarsysInitialization(NameWebEmarsysInitalizationTag, tagTemplate)); err != nil { + return err + } + } + + { // create event tags + tagID, err := tm.LookupVariable(googletag.NameGoogleTagID) + if err != nil { + return err + } + + eventParameters, err := googletag.CreateWebEventTriggers(tm, cfg.WebContainer) + if err != nil { + return err + } + + for event := range eventParameters { + eventTrigger, err := tm.LookupTrigger(commontrigger.EventName(event)) + if err != nil { + return errors.Wrap(err, "failed to lookup event trigger: "+event) + } + + eventSettings, err := tm.LookupVariable(commonvariable.GoogleTagEventSettingsName(event)) + if err != nil { + return errors.Wrap(err, "failed to lookup google tag event setting: "+event) + } + + if _, err := tm.UpsertTag(containertag.NewGoogleAnalyticsGA4Event(event, tagID, eventSettings, eventTrigger)); err != nil { + return err + } + } + } + + return nil +} diff --git a/pkg/provider/emarsys/web/tag/emarsysinitialization.go b/pkg/provider/emarsys/web/tag/emarsysinitialization.go new file mode 100644 index 0000000..71b3be0 --- /dev/null +++ b/pkg/provider/emarsys/web/tag/emarsysinitialization.go @@ -0,0 +1,17 @@ +package tag + +import ( + "github.com/foomo/sesamy-cli/pkg/tagmanager/web/trigger" + "github.com/foomo/sesamy-cli/pkg/utils" + "google.golang.org/api/tagmanager/v2" +) + +func NewEmarsysInitialization(name string, template *tagmanager.CustomTemplate) *tagmanager.Tag { + ret := &tagmanager.Tag{ + Name: name, + FiringTriggerId: []string{trigger.IDConsentInitializtion}, + TagFiringOption: "oncePerEvent", + Type: utils.TemplateType(template), + } + return ret +} diff --git a/pkg/provider/emarsys/web/template/emarsysinitializationtag.go b/pkg/provider/emarsys/web/template/emarsysinitializationtag.go new file mode 100644 index 0000000..75c86ff --- /dev/null +++ b/pkg/provider/emarsys/web/template/emarsysinitializationtag.go @@ -0,0 +1,14 @@ +package template + +import ( + "fmt" + + "google.golang.org/api/tagmanager/v2" +) + +func NewEmarsysInitializationTag(name string) *tagmanager.CustomTemplate { + return &tagmanager.CustomTemplate{ + Name: name, + TemplateData: fmt.Sprintf(EmarsysInitializationTagData, name), + } +} diff --git a/pkg/provider/emarsys/web/template/emarsysinitializationtagdata.go b/pkg/provider/emarsys/web/template/emarsysinitializationtagdata.go new file mode 100644 index 0000000..3ad1646 --- /dev/null +++ b/pkg/provider/emarsys/web/template/emarsysinitializationtagdata.go @@ -0,0 +1,254 @@ +package template + +const EmarsysInitializationTagData = `___INFO___ + +{ + "type": "TAG", + "id": "cvt_temp_public_id", + "version": 1, + "securityGroups": [], + "displayName": "%s", + "brand": { + "id": "brand_dummy", + "displayName": "sesamy", + "thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/7QCcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAIAcAmcAFFNzN0J2MG8zM0dlUE1tOW1vYThYHAIoAGJGQk1EMDEwMDBhYzEwMzAwMDBjOTBhMDAwMGFkMGUwMDAwNGUxMDAwMDAxMDEyMDAwMGYyMTQwMDAwOWUxOTAwMDBkNTFkMDAwMDYxMWYwMDAwZjkyMDAwMDAyYjI5MDAwMP/iAhxJQ0NfUFJPRklMRQABAQAAAgxsY21zAhAAAG1udHJSR0IgWFlaIAfcAAEAGQADACkAOWFjc3BBUFBMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD21gABAAAAANMtbGNtcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmRlc2MAAAD8AAAAXmNwcnQAAAFcAAAAC3d0cHQAAAFoAAAAFGJrcHQAAAF8AAAAFHJYWVoAAAGQAAAAFGdYWVoAAAGkAAAAFGJYWVoAAAG4AAAAFHJUUkMAAAHMAAAAQGdUUkMAAAHMAAAAQGJUUkMAAAHMAAAAQGRlc2MAAAAAAAAAA2MyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRleHQAAAAARkIAAFhZWiAAAAAAAAD21gABAAAAANMtWFlaIAAAAAAAAAMWAAADMwAAAqRYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9jdXJ2AAAAAAAAABoAAADLAckDYwWSCGsL9hA/FVEbNCHxKZAyGDuSRgVRd13ta3B6BYmxmnysab9908PpMP///9sAQwAJBgcIBwYJCAgICgoJCw4XDw4NDQ4cFBURFyIeIyMhHiAgJSo1LSUnMiggIC4/LzI3OTw8PCQtQkZBOkY1Ozw5/9sAQwEKCgoODA4bDw8bOSYgJjk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5/8IAEQgCSAJIAwAiAAERAQIRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAEBQEDBgL/xAAaAQEAAwEBAQAAAAAAAAAAAAAAAQIDBAUG/8QAGgEBAAMBAQEAAAAAAAAAAAAAAAECAwQFBv/aAAwDAAABEQIRAAAB7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgjOIlVXG+901zNwnQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx4Rs81dZXmuKuNmnFjOEY2tzTXOnqhboAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDLEVWVpp4NOSyr/CvGEZgAWtzTXOnqhboAAAAAAAAAAAAAAAAAAAAAAAAAAGDLxXRnZwafRXjlxM4pyAqAAABa3NNc6eqFugAAAAAAAAAAAAAAAAAAAAAAAAYM4j1cY29ZWeacWzWV5gQAAAAABa3NNc6eqFugAAAAAAAAAAAAAAAAAAAAAAx5R7xW1lee4q4avFnBXAAAAAAAA9T5vXzLiRbsjSi3YE2AAAAAAAAAAAAAAAAAAAAMaFZGuorqctrWa1eNnCMgAAAAAADfaTtUWVr6v2a9mVuoEgAAAAAAAAAAAAAAAAAADBl5gxSfEpo1eOdCwpyAoAAAAAAMmFhaW6Ka0nZt24yW3BIAAAAAAAAAAAAAAAAAAAwZaKyMrauqfFOPdpK8gIAAAAAAG5On3bWNuqps92b9uMk6gAAAAAAAAAAAAAAAAAAAAMaaOMLmrr1OHOCvOAAAAAAAZmrQZNzLv2V8/ObdgTcAAAAAAxir01bYBcAAAAAAAAAAAAABC5/oOez80K8gAAAAABtsp0qrG22X7dG/K3WCQAAAAADGqjd4hR/PtKjYeZaXNhTfaoHZAAAAAAAAAAAAAAELnuh57PzQryAAADJhMtLb09pY5t2+fRboBIAAAAAB5j5JOiHr82+7SebYKAJc2FN+gzDsgAAAAAAAAAAAAACFz3Q89n5oV5ABgyj6L6yd1c037KZwNi6uuVllG2QkAAAAIGuJzzMjRMeZb15OGwVAAAS5sKb9BmHZAAAAAAAAAAAAAAELnuh57PzRrry7PMXVptv04abBNgAEuIT01twe6Ne5UFzXbcwi2TBlGicczYuh5lg5LBAAAAACXNhTfoMw7IAAAAAAAAAAAAAAhcz2VbHNy+uwr75BIAAAAAB78C5u+Lm47dNF8vnuwOeQAAAAAAD3K6I8zfPr3aBvAAAAAAAAAAAAAAACFNI5aq73ROXEL2mnHWJqAAAAAmwpvPe6HzHoAAAAABI3y+usKXvz6dcZOyAkAAAAAAAAAAAAAAAAAA17CKOk7fzOfBOqo5xgiaAAAJsKbz3uh8x6AAAA9Wecy5XfWFL959KodMAAAAAAAAAAAAAAAAAAAAAAAMZECj6vCnBY7WkthSvficwE2FN573Q+Y9AAbtI07Ju70axpOXpVDUAAAAAAAAAAAAAAAAAAAAAAAAAAABqpr4rw2nvam2PMTfPvCty9Sfn+6LIme/Trq2noVCQSAAAAACASAAAAAAAAAAAAAAAAAAAAAAAAxFlojz6EhIAAAAAA81kxaQaGNvn0llRXuVwpYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYMotPet5VUuN6bdRtQJXN7RXvFsGdgAAAAAAAAAAAAAAAAAAAAAAAAAAAB4PeKqn0pfU8F0UDWoAAFze0V7xbBnYAAAAAAAAAAAAAAAAAAAAAAAAAAxFRL00VbvS4qtbegXgAAAAC5vaK94tgzsAAAAAAAAAAAAAAAAAAAAAAAAeKqYt6+h0dGc2EbUCwAAAAAAC5vai34dgpYAAAAAAAAAAAAAAAAAAAAAYhnESn0re1FRjoz9+DWoSAAAAAAG6Gn1dWuN6S3kue4VsAAAAAAAAAAAAAAAAAAAANZsxT1OtL2nhuigaVAAAAAAAFjVXS76ZhpWWXphcIkAAAAAAAAAAAAAAAAAAAAABzfSc3rStHZkAAAAAAAb7ak0tpd++fTRvyxsCQAAAAAAAAAAAAAAAAAAAAAAAHN9JzetK0dmQAAAAyYWVxlahuLHPPpjJnYAAAAAAAAAAAAAAAAAAAAAAAAAABzfSc3rStHZkAAN8NHu7tcL0lvvYaYyVkAAAAAAAAAAAAAAAAAAAAAAAAAAAABzfSc3rStHZkZsqqybfSsNK6xywuESAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5vpId68za3Xq0atxlYEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/xAAnEAACAgEDBAMAAwEBAAAAAAACAwABBDBAUBEgMTMFEGASE4AUIf/aAAgBAAABBQL/AHd/Kuv4ZmQARmSZzB8/g7vpGZQ1GOM/vB8/gSKhjMuGwj7cHzz5tAIzLu4V2V92D551jwCMyTLSwfPNdYzKAYx5nqYPnmLKhpmXVQ2metg+eWNghGZcIiK9fB88oxwBGZRXLu72WD55JmSAxmQZ7ReMZxKaVyF30jMoajHGezqru14pXFpAOQIxGmZcMyPZiBHF4kBYhXHsaARmWVy7sr2S1GyLxBqUNVyDMgAjMky2i8czi8YB5DrGZQDGPM9n5i8Uyi0AHIEVDTMuobCPZiNla8S7gLEOQNghGZd3CKyvZAsji8SoI0Ncex4BGZRlPOzBBnF4ojOnTkGn/WDHme0XjGUXjgGzu+kE6Lf5fo2NVZWvEK4tQBs7KqhNl3dxG/y/RrgBHF4kEBDZkY1Cbd9iN/l+jVWo2ReKNSqqtmTaqEwr7kb/AC/RprxzOLxgHZ9ekJ1QjstBG/y/Ro2yojJ/rtOQpuysqqE6Xd3pI3+X6O676S2S7u+xWY1cTmKZrEdDCbdzzqI3+X6OyyqpbNFWQxUTngUoqKtAmVUJl3ro3+X6PqzqpZ3eqtprtPyEBgMrsJtVCMi2KN/l+i2VLO72IlY2nPIYvIWyidLK72aOAdhKZHYjV7PE9uyobKCmVXTgnYymx2CwZdXV6+J7dgIFcFVVw7EgynfH3DAgvVxPbrCq7grGuLIBOnfHjcalitTE9unVdYKoI1XH9OsdgrOOxWq0sT26NDdwUyqquUdiKbHYTA0MT294hdwVVzLULbHYBVCGwvsxPb2iu7grqudNYsp3x8Yo1X9Ynt+xVdwQofwN1Vx2Aso3GaqYntqruCmUNV+G/wCdX8+mzblrCYr7cX4S7qqbmhUY9jPr43z+CNgrpudDMj7PjvP4Br1rjcwyl3d32/HeeeblrCNymHo/HeebIqGm5o1GOYzT+O88ybQXG50MyO9T47zy7cha4zMMpd3d63x3nlW5awjcljNl8d55IioabmjUY42bTAWYcixoLjc64Rkd7IRsrVhFcWkF8g3JWuNzDKX/AO3slrNkVg1AAQrjusbmLGMyWM2i8djIrDAZVdOPIxCm5tRjTZtF4jDisZa+Sz/dshGytWFdxaQXymf79gtRsisGqggI1yuf79ZWMxkVhrGdOYz/AH6fmLwzKKxlr5vP9+iIkdqwbi1Auucz/f3rSbIrCGoI0Nc9n+/tVjMZFYiw/BZ/v+qq7isMyisda/wmf7wAjtWDFqBf4Y8cGMEaGv8ATf8A/8QAJhEAAgEDAwQDAQEBAAAAAAAAAQIAAxExBDBAEBIgMjNQUVJwIf/aAAgBAhEBPwH/AAp66pKb963+hJtH1SriPXZ+mm+PnlguZU1YHrHqs2fDTfHzXqKmY+r/AJjOWz5ab4+W9ZEzH1THEJvnY03xjkvqUWPqGfZSmzYiaT+oqhRYcYkDMqasD1j1mfOylF3xKelVcwC3GZ1XMqav+Yzs+dlNMzZiadV471lTMfVk+sJJzsBSZT0pPtEoqmOPUrrTzH1LNsqjNiJpP6ioq45Os9thKLPiJpAPaAAY2bdDwNZ7eVPTu8TTKuzadvgeBrPbqP8AsWkTFULBV/YCD52lvI8DWe0AJi0f2BQPAG0Wr+wMD1tLbB4Faj3m87e3Zpub2gGzeHg2hpfkKkedP22Ly/GNMGFCPGn7eXdL8ooDGpkdaft1vO7nlQY1L8iCzS87vrLwvFx9CTaF+q455aFvFccy8Lwm/muOVeF5fZXHILQvtBIBbjloWOzaBIByGxshbwJy3x5hYF5r48QkA5746WgSW+hYXgT/AAf/xAAqEQACAgAFAgYCAwEAAAAAAAABAgADBBEwMUAgMgUQEiEzUEFREyJwYf/aAAgBAREBPwH/AAr1QfRFoW8l2+gLTPoXbm5wt1rty84W0RtySZ6tHKBeQWhOjlAvILTPRCzLj5wtpBZlxycoW0coF0ScorBvccBtDKBdFnC7y3xBR7JLL3s3MwPwjgN1BYF0bLkr7jLfEfwkexnP9j54H4RwG6AkCiZaFuKrr3luPdvZfaFi3uenA/COA0ygSAZdOXnnLcbWm3vLcbZZoYH4RwMoNG5vQhaW4l7Nzo1YayzYSiv+JPTws9DFfEesDOVYKx/+SrBV18bOZ9OK+I9KqW2lWAdu72lWGrr2HKzmfniviPmlTP2iVeHfl5XUlfaOfnMV8RleHezYSrw9R7vFQKMh9ERn7GAAaAUnaLR+5YMmy+hVC0WkDeAZeVvdz1qYxagOm3u5gBO0WkneKir1293KVS20Wj9wKBo2HNuQtZMWkDeZaBOW8a8fiM5bfjrUTFqVdEsBvGv/AFCxO/Ip7tFrFWNcTty6e7ra5RGtY82nu6CQN414/ELlt+fT3eTMF3jX/qEk/Q1t6TnGuJ2/wf8A/8QAKRAAAQIEBgICAwEBAAAAAAAAAQARAiEiQDAxUFFhgRIgA2AQI5GAQf/aAAgBAAAGPwL/AHc30fc8KUgo/orQ1FZy4/Mf0JyWVA7VR9Y/oEyqAycl/ePXs3KlIYUeuSqKzYcYkesuSqQ6mcaPV6iqB/U8Rewj1WZmqaU5so9T3K2FpsFL/uoTVNSmbNgqpKQ1ByVQP6qi9nSHVZ/ipDahMqkMnJs5BPEXUtQzc8KVItMmHKnM6jTUVmw4s5KqlZahNUB1UbNgHVZVI1CZVAVRezpCrKYBtQmZqmm0yYcqqo6iYlmw4tJyCyc82kr+KyYBVFlIWc1JTRv4rCkOqz/EwFpKXob+LGkFVNStNvY38WJsFubSU8E38WHOAFUxT2NlNSU8I38WBL1z8hypnxPONNSxTfxe0sGmKWxTRjxKcFxhbY5v4rF4ImTfLD2E8MQPrKdkb+KzeEkFN8g8uVTEpKdmdAlSeFl5Diz6s5KehzhnuFRWExzsOrLfR2jhdP8AHE/BTRQkY3WPtpjRAEJ/jLHYqqHE6xZ6jTQeFk43GF1hSU1LVMmO4VNYwOsGc9ZrhT/GfLgpogQfXr2215og6f44uiq4W/PXpOX0KaeCkqcMtwulJTUvo3mIWNpn5HhRPID6K5VA8lOKW34j+hvEWTfHD2VUX9I/oMzPZNAPFOS/tHr8qjws/EcYMeuOSyaAeSqilthx61VEy/WOyniJOLHrEzPYJoaQnJx49WlUeFn4jiyj1N4iwTQB1VFaRGIM+o1RMv1huSniL2bQhyqyypGoZudgqaQns6YXX7D0E0IbUGhqKzYbC0kGG5VVRUtPeIsv1h+SqorSqkLJzudS6s2hDqstwFTDqnVjTCqy/ATQhtW6x8mG5TxVHWesWqkLJzudb6wmhDr9hbgKmFtd6wKYU8ZdNCG1/r2yYcqdR5+hdflgqqQpCe5+idJoQSv2HoKmFvo3nF/EwDD/AE5//8QAKRAAAQIEBQQDAQEBAAAAAAAAAQARITFRYUBBUHGBIDChsRBgkfDRgP/aAAgBAAABPyH/ALtdAhAQ4+jOoU9hIBwl630QIOSwRf8AAkpu2j5ep9CDMgugiDlyJxTbLp9TX3QlxiygW4KdCK/X6mukqa2AUEWJJLkkns+prZAKEcRQbZdx6mstRAXUCe1yVJ6Zd71NWdAnCEcwYujqJYD1NV8LhNO4Flc0QcJN8F4g1JwoWDaCgwNoYSJEXihRcSZjqAQcgAnQC7wqC0GDYQSbKKm2makO9c9PdNpAIcnLoRcuDGGIhzHgRgARtPCw3pmoS1qZp8Im+DoHXJTBfCEsAAshpzqFbBIDwJokmJjg4lukj4byAbTiiAiYKAcCSgZtMGAJMBJomAwPKkbjUoAIac7DACCg4qVM02ywbkRWUYYsEPYITaePcYUIYuU5iFfBztN8kBFw0CZiC2nusxKAoBA8okk5JJrg42LxGI8hAJIahCV2UG2WDTkonypqN7hGwQAclkRIyY/0veCfCJsoy1oJoLDeuabBTkyLl5RFyJU+P+t7wBRipm8SDGQGDmpjRQJBJMTE/M+P+t771E6mSjxv8IKwMLYJ1AxE2VldU+P+t77jMSN6ai5G8gGwRAHMEJBUyPYnx/1vfZJacEJIOo+PqJhQRjYHBCXIBUPJR1y7U+P+t76wTFU/Kmh6GgGzn/UyBzy/2n7syKSWFUSScknuT4/63vpmJRzSiSZx7EL/AEATEVWmE1FUB7DqFzKk8Hfnx/1vfzeipdAd1zBAQYfzJNhNugkCah0RTQsMDPj/AKntCyis7hgbmKBTMxUQKewITBgUCQvdTtg58fIdRAH8/wDCdSLn/ODnbsHLiAJ3sgAwDaCyiLW0KdSViRTCCAyOAnbsDFWYVUyiQDaKyawQD+RunPm/enbu/MoFIQ50u0KCF5BwEVjAVy/e5O3dwhMASimdrKTjTyAMQ4TkfUfidCW93tTt3alJ0DPwgrA2psnAnjii/An+IggsQQeudu7EjEKoaMRAAS1dkIgE1zUnLYKt2ojpnbuqbwKPzKbXGrxugF2X8TTUJdl8zt3yATAB1PCSIRr9BCEACDVOJfMFnNxPiS06qeApSb6KyaYbMEAEsE6gYsEZ8GDAfRX0ACpUBMdclOaxL48MfQ24wX8A/Efc+7o8cfQYLtk06ABWZTyRVPV4414llACsJAxYTfvZ8ca4xEFSouirIKeliXb8ca0IcSEMGf4knMS/d8caxAX+Qn4PmKcQJv3/ABxqpIETBQQ/E/VBth/rBeONSKZwqEqaLUwCNxCKZYOe6dFBjPqDoI4rERBIeBK+DcwoAKKtaCJQ+CDXNNpzqBHmCcxwpoi4JJrgyjGuyUw6hlELaeQAclgnHgpfqegeEYRvPCCZjzpIAMAApp7QIXKDg64ETjEUywYBJYAumw8qf4osOWJtRl7cG9iVlHm/IhbCBrmm1OVtwJeMRXJRLxhNIBbVpW3vsRC55EpIAAwDDWJW3uAEmAJNAms8qaYiOYa3K29p8ErIiKQyBXJtclbewbjEVyUUZ0EAmcAoBr8rb1Mx3SRQfE/EwEB9BlbfkgwSaBRY/cs0eR9ElbU5iWRDFn+JoAwvoyOUwaKCYioAIf8ATf8A/9oADAMAAAERAhEAABDzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzglbrzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzilRuyvzzzzzzzzzzzzzzzzzzzzzzzzzzzzywTezzzyvzzzzzzzzzzzzzzzzzzzzzzzzzzywcRbzzzzyvzzzzzzzzzzzzzzzzzzzzzzzzzRDVzzzzzzzyvzzzzzzzzzzzzzzzzzzzzzzgl913zzzzzzzU8fzzzzzzzzzzzzzzzzzzzziUdyzzzzzzzzr1wzzzzzzzzzzzzzzzzzzzywP27zzzzzzzzGO0zzzzzzzzzzzzzzzzzzzgQzZ/zzzzzzznNqwzzzzzzzzzzzzzzzzzzzzh033zzzzzz3PHozzzzzzg4vzzzzzzzzzzzzzyy/zzzzzzzG3wxzzzzzg0zIPzzzzzzzzzzzzzzz/wA88845TNc888884JwSCCD888888888888888/889hL7K08888ymiACCCCD888888888888888/+sqE8ss4GuAHhACCCCCCD888888888888884jG088888utswCCCCCCCCCI888888888888888sY+z+8888+9CCCCCCELLuM88888888888888888sdFiU8888CCCCEJqMc888888888888888888888sc2P188CCFPlcc88888888888888888888888888Mqw4GItO8888882888888888888888888888888sdsM88888oirj88888888888888888888888888888880BqCAq888888888888888888888888888880XSgAAAq888888888888888888888888884rNjACAAAAq888888888888888888888888ompLAAAAAAAEC88888888888888888888882QxiiCAAAAAD+Tc88888888888888888888sJEAAAAAAACbExM8888888888888888888884VAAAAAAAIFU/sc8888888888888888888888oVAAAACABIMM8888888888888888888888888oVAACXbks8888888888888888888888888888oVANEtM8888888888888888888888888888884QePc888888888888888888888888888888888cs8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888//EACMRAQACAgEEAwEBAQAAAAAAAAEAESExQBAgMFBBUXFwYYH/2gAIAQIRAT8Q/hWOW2VHoYC1mKzY9V0dNXPOtVMALiOfZq5oluo7gRO10rs1cveMzG4kRXl6ALRbMSZZjjBLdyu9XG4ZlwBo4xtqYIXGsvANzWMf7MhmwBRxhbdT4T/2OW/ACuJm8CZurZRxtkzMXgR21fgZoJlsIVhx8RtMeYIqtvgdo3PncNo8nT+eDVMTN5QWh4AYSATfgafztBdTIVRM25YAYPAJh9oAdd+Bp/OodJlmOibhagSzvEwkK7d+Bp/IpREcxjQ7EWIpGteo2BPBvwKafiqXfdcGooKAeFBFbfBQ7huY35L7tHfcSRbxUHc1mO79Hcginl/pIiOemjqgj9Iq87exTMINxBH6Rb9Eg+FBufCRLZ9CMI6i301c8SK9urmIIBqL3tXKST4SKd+DMFcgBEdRz4AXUR3B4y6gkV4RM+yAa5D8JIA3Ar0IrBPQgLqI7gnoQTPsgDXoUFQDcAP4N//EACMRAQACAgEDBQEBAAAAAAAAAAEAESExQCAwQRBQUWGhcIH/2gAIAQERAT8Q/hSCKy/YgIj6aOfZBNRT0aOagnhIq9WjlpIviLfY1ckSKeyJg+YAcbEEiPZGwDcMcZQnwxTvsowJ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" + }, + "description": "Managed by Sesamy. DO NOT EDIT.\nSend events to Emarsys", + "containerContexts": [ + "WEB" + ] +} + + +___TEMPLATE_PARAMETERS___ + +[ + { + "type": "TEXT", + "name": "merchantId", + "displayName": "", + "simpleValueType": true + } +] + + +___SANDBOXED_JS_FOR_WEB_TEMPLATE___ + +const Math = require('Math'); +const JSON = require('JSON'); +const gtagSet = require('gtagSet'); +const sendPixel = require('sendPixel'); +const logToConsole = require('logToConsole'); +const generateRandom = require('generateRandom'); +const getCookieValues = require('getCookieValues'); +const encodeUriComponent = require('encodeUriComponent'); +const createArgumentsQueue = require('createArgumentsQueue'); + +// --- Config + +const sessionId = getCookieValues('emarsys_s')[0] || null; +const visitorId = getCookieValues('emarsys_cdv')[0] || null; +const pageViewId = generateRandom(0, Math.pow(2, 31)); + +logToConsole(JSON.stringify({ + sessionId: sessionId, + visitorId: visitorId, + pageViewId: pageViewId, +})); + +const gtag = createArgumentsQueue('gtag', 'dataLayer'); + +// set page view id +gtag('set', 'emarsys', { page_view_id: pageViewId }); +let query = []; +if (sessionId) query.push('s='+encodeUriComponent(sessionId)); +if (sessionId) query.push('s='+encodeUriComponent(sessionId)); +if (pageViewId) query.push('pv='+encodeUriComponent(pageViewId)); + +// call emarsys client +sendPixel("/gtag/js/emarsys?"+query.join('&')); + +// Call data.gtmOnSuccess when the tag is finished. +data.gtmOnSuccess(); + + +___WEB_PERMISSIONS___ + +[ + { + "instance": { + "key": { + "publicId": "logging", + "versionId": "1" + }, + "param": [ + { + "key": "environments", + "value": { + "type": 1, + "string": "debug" + } + } + ] + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "write_data_layer", + "versionId": "1" + }, + "param": [ + { + "key": "keyPatterns", + "value": { + "type": 2, + "listItem": [ + { + "type": 1, + "string": "emarsys.*" + } + ] + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "send_pixel", + "versionId": "1" + }, + "param": [ + { + "key": "allowedUrls", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "access_globals", + "versionId": "1" + }, + "param": [ + { + "key": "keys", + "value": { + "type": 2, + "listItem": [ + { + "type": 3, + "mapKey": [ + { + "type": 1, + "string": "key" + }, + { + "type": 1, + "string": "read" + }, + { + "type": 1, + "string": "write" + }, + { + "type": 1, + "string": "execute" + } + ], + "mapValue": [ + { + "type": 1, + "string": "gtag" + }, + { + "type": 8, + "boolean": true + }, + { + "type": 8, + "boolean": true + }, + { + "type": 8, + "boolean": false + } + ] + }, + { + "type": 3, + "mapKey": [ + { + "type": 1, + "string": "key" + }, + { + "type": 1, + "string": "read" + }, + { + "type": 1, + "string": "write" + }, + { + "type": 1, + "string": "execute" + } + ], + "mapValue": [ + { + "type": 1, + "string": "dataLayer" + }, + { + "type": 8, + "boolean": true + }, + { + "type": 8, + "boolean": true + }, + { + "type": 8, + "boolean": false + } + ] + } + ] + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + } +] + + +___TESTS___ + +scenarios: [] + + +___NOTES___ + +Code generated by sesamy. DO NOT EDIT. +` diff --git a/pkg/provider/googleanalytics/constants.go b/pkg/provider/googleanalytics/constants.go index 3587f9d..8807690 100644 --- a/pkg/provider/googleanalytics/constants.go +++ b/pkg/provider/googleanalytics/constants.go @@ -5,6 +5,8 @@ const ( Name = "Google Analytics" NameGoogleAnalyticsGA4Client = "Google Analytics GA4" NameGoogleAnalyticsGA4ClientTrigger = "Google Analytics GA4 Client" + NameGoogleGTagClientTemplate = "Google gtag.js" + NameGoogleGTagClient = "Google gtag.js" NameMeasurementProtocolGA4Client = "Measurement Protocol GA4" NameMeasurementProtocolGA4ClientTrigger = "Measurement Protocol GA4 Client" ) diff --git a/pkg/provider/googleanalytics/server.go b/pkg/provider/googleanalytics/server.go index c242d92..489c59d 100644 --- a/pkg/provider/googleanalytics/server.go +++ b/pkg/provider/googleanalytics/server.go @@ -2,7 +2,9 @@ package googleanalytics import ( "github.com/foomo/sesamy-cli/pkg/config" + client2 "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/client" containertag "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/tag" + template2 "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/template" "github.com/foomo/sesamy-cli/pkg/provider/googletag" "github.com/foomo/sesamy-cli/pkg/tagmanager" commontrigger "github.com/foomo/sesamy-cli/pkg/tagmanager/common/trigger" @@ -40,6 +42,18 @@ func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitor return err } } + + if cfg.GoogleGTag.Enabled { + template, err := tm.UpsertCustomTemplate(template2.NewGoogleGTagClient(NameGoogleGTagClientTemplate)) + if err != nil { + return err + } + + _, err = tm.UpsertClient(client2.NewGoogleGTag(NameGoogleGTagClient, cfg.GoogleGTag, template)) + if err != nil { + return err + } + } } { // create tags diff --git a/pkg/provider/googleanalytics/server/client/googlegtag.go b/pkg/provider/googleanalytics/server/client/googlegtag.go new file mode 100644 index 0000000..a1e8c6e --- /dev/null +++ b/pkg/provider/googleanalytics/server/client/googlegtag.go @@ -0,0 +1,24 @@ +package client + +import ( + "strconv" + + "github.com/foomo/sesamy-cli/pkg/config" + "github.com/foomo/sesamy-cli/pkg/utils" + "google.golang.org/api/tagmanager/v2" +) + +func NewGoogleGTag(name string, cfg config.GoogleGTag, template *tagmanager.CustomTemplate) *tagmanager.Client { + return &tagmanager.Client{ + Name: name, + Priority: cfg.Priority, + Parameter: []*tagmanager.Parameter{ + { + Key: "patchEcommerceItems", + Type: "boolean", + Value: strconv.FormatBool(cfg.EcommerceItems), + }, + }, + Type: utils.TemplateType(template), + } +} diff --git a/pkg/provider/googleanalytics/server/template/googlegtagclient.go b/pkg/provider/googleanalytics/server/template/googlegtagclient.go new file mode 100644 index 0000000..8271479 --- /dev/null +++ b/pkg/provider/googleanalytics/server/template/googlegtagclient.go @@ -0,0 +1,14 @@ +package template + +import ( + "fmt" + + "google.golang.org/api/tagmanager/v2" +) + +func NewGoogleGTagClient(name string) *tagmanager.CustomTemplate { + return &tagmanager.CustomTemplate{ + Name: name, + TemplateData: fmt.Sprintf(GoogleGTagClientData, name), + } +} diff --git a/pkg/provider/googleanalytics/server/template/googlegtagclientdata.go b/pkg/provider/googleanalytics/server/template/googlegtagclientdata.go new file mode 100644 index 0000000..6737886 --- /dev/null +++ b/pkg/provider/googleanalytics/server/template/googlegtagclientdata.go @@ -0,0 +1,225 @@ +package template + +const GoogleGTagClientData = `___INFO___ + +{ + "type": "CLIENT", + "id": "cvt_temp_public_id", + "version": 1, + "securityGroups": [], + "displayName": "%s", + "brand": { + "id": "brand_dummy", + "displayName": "Foomo Sesamy", + "thumbnail": "data:image/png;base64,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\u003d" + }, + "description": "Managed by Sesamy. DO NOT EDIT.\nServe patched gtag.js version", + "containerContexts": [ + "SERVER" + ] +} + + +___TEMPLATE_PARAMETERS___ + +[ + { + "type": "GROUP", + "name": "patchesConfigGroup", + "displayName": "Patches", + "groupStyle": "ZIPPY_OPEN_ON_PARAM", + "subParams": [ + { + "type": "CHECKBOX", + "name": "patchEcommerceItems", + "checkboxText": "Ecommerce Items", + "simpleValueType": true, + "defaultValue": true, + "help": "Allows sending 'items' not only for the hard coded events" + } + ] + } +] + + +___SANDBOXED_JS_FOR_SERVER___ + +const logToConsole = require('logToConsole'); +const claimRequest = require('claimRequest'); +const getRequestPath = require('getRequestPath'); +const getGoogleScript = require('getGoogleScript'); +const setResponseStatus = require('setResponseStatus'); +const setResponseHeader = require('setResponseHeader'); +const getRequestQueryParameter = require('getRequestQueryParameter'); +const getContainerVersion = require('getContainerVersion'); +const setResponseBody = require('setResponseBody'); +const returnResponse = require('returnResponse'); + +// --- Validation --- + +if (getRequestPath() !== '/gtag/js') { + return; +} + +claimRequest(); + +const id = getRequestQueryParameter('id'); +const containerVersion = getContainerVersion(); + +getGoogleScript('GTAG', {id: id, debug: containerVersion.debugMode, timeout: 500}).then((result) => { + let script = result.script; + // apply patches + + // allow sending ecommerce 'items' not only for the hard coded once + if (data.patchEcommerceItems) { + script = script.replace('if(a.metadata.is_ecommerce){', 'if(true){'); + } + + // copy metadata header + for(let key in result.metadata) { + setResponseHeader(key, result.metadata[key]); + } + // set response + setResponseBody(script); + setResponseStatus(200); + returnResponse(); +}); + + +___SERVER_PERMISSIONS___ + +[ + { + "instance": { + "key": { + "publicId": "read_request", + "versionId": "1" + }, + "param": [ + { + "key": "requestAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "headerAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "queryParameterAccess", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "return_response", + "versionId": "1" + }, + "param": [] + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "logging", + "versionId": "1" + }, + "param": [ + { + "key": "environments", + "value": { + "type": 1, + "string": "debug" + } + } + ] + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "access_response", + "versionId": "1" + }, + "param": [ + { + "key": "writeResponseAccess", + "value": { + "type": 1, + "string": "any" + } + }, + { + "key": "writeHeaderAccess", + "value": { + "type": 1, + "string": "specific" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "send_http", + "versionId": "1" + }, + "param": [ + { + "key": "allowedUrls", + "value": { + "type": 1, + "string": "any" + } + } + ] + }, + "clientAnnotations": { + "isEditedByUser": true + }, + "isRequired": true + }, + { + "instance": { + "key": { + "publicId": "read_container_data", + "versionId": "1" + }, + "param": [] + }, + "isRequired": true + } +] + + +___TESTS___ + +scenarios: [] + + +___NOTES___ + +Code generated by sesamy. DO NOT EDIT. +` diff --git a/pkg/provider/googletag/server.go b/pkg/provider/googletag/server.go index 10f809d..a15db67 100644 --- a/pkg/provider/googletag/server.go +++ b/pkg/provider/googletag/server.go @@ -18,7 +18,7 @@ func Server(tm *tagmanager.TagManager) error { return nil } -func CreateServerEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (map[string][]string, error) { +func CreateServerEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (map[string]map[string]string, error) { previousFolderName := tm.FolderName() tm.SetFolderName("Sesamy - " + Name) defer tm.SetFolderName(previousFolderName) diff --git a/pkg/provider/googletag/web.go b/pkg/provider/googletag/web.go index 5c29250..3e3ace3 100644 --- a/pkg/provider/googletag/web.go +++ b/pkg/provider/googletag/web.go @@ -50,7 +50,7 @@ func Web(tm *tagmanager.TagManager, cfg config.GoogleTag) error { return nil } -func CreateWebEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (map[string][]string, error) { +func CreateWebEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (map[string]map[string]string, error) { previousFolderName := tm.FolderName() tm.SetFolderName("Sesamy - " + Name) defer tm.SetFolderName(previousFolderName) @@ -65,14 +65,14 @@ func CreateWebEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) ( return nil, err } - settings := make(map[string]*api.Variable, len(parameters)) - for _, parameter := range parameters { - if settings[parameter], err = tm.UpsertVariable(variable.NewDataLayerVariable(parameter)); err != nil { + variables := make(map[string]*api.Variable, len(parameters)) + for parameterName, parameterValue := range parameters { + if variables[parameterName], err = tm.UpsertVariable(variable.NewDataLayerVariable(parameterValue)); err != nil { return nil, err } } - if _, err := tm.UpsertVariable(containervariable.NewGoogleTagEventSettings(event, settings)); err != nil { + if _, err := tm.UpsertVariable(containervariable.NewGoogleTagEventSettings(event, variables)); err != nil { return nil, err } } diff --git a/pkg/provider/googletag/web/variable/googletageventmodel.go b/pkg/provider/googletag/web/variable/googletageventmodel.go deleted file mode 100644 index 1bd492a..0000000 --- a/pkg/provider/googletag/web/variable/googletageventmodel.go +++ /dev/null @@ -1,14 +0,0 @@ -package variable - -import ( - "github.com/foomo/sesamy-cli/pkg/tagmanager/web/variable" - "google.golang.org/api/tagmanager/v2" -) - -func GoogleTagEventModelName(v string) string { - return variable.DataLayerVariableName("eventModel." + v) -} - -func NewGoogleTagEventModel(v string) *tagmanager.Variable { - return variable.NewDataLayerVariable("eventModel." + v) -} diff --git a/pkg/provider/microsoft/server/template/data/conversion/code.js b/pkg/provider/microsoft/server/template/data/conversion/code.js new file mode 100644 index 0000000..34f0a28 --- /dev/null +++ b/pkg/provider/microsoft/server/template/data/conversion/code.js @@ -0,0 +1,200 @@ +const sendHttpGet = require('sendHttpGet'); +const getEventData = require('getEventData'); +const generateRandom = require('generateRandom'); +const logToConsole = require('logToConsole'); +const Math = require('Math'); +const encodeUriComponent = require('encodeUriComponent'); +const JSON = require('JSON'); +const getCookieValues = require('getCookieValues'); +const setCookie = require('setCookie'); +const parseUrl = require('parseUrl'); + + +let clickid; +function isNotEmpty(obj) { + if (obj === undefined || obj === null || obj.toString() === "" ) { + return false; + } else { + return obj; + } +} + +let msquery = () => { + const url = parseUrl(getEventData('page_location')); + if (url && url.searchParams.msclkid) { + return url.searchParams.msclkid; + } else { + return false; + } +}; + +function setUETCookie(clickid) { + setCookie('_uetmsclkid', "_uet"+clickid, {"expires":7776000000, httpOnly: false}); + logToConsole("Cookie set: " + clickid); +} + +if(data.first_click) { + if (isNotEmpty(data.msclkidCookie) || isNotEmpty(getCookieValues('_uetmsclkid'))) { + let clickid_cookie = getCookieValues('_uetmsclkid')[0]; + clickid = (isNotEmpty(data.msclkidCookie) || (clickid_cookie.substring(4))); + clickid += "-0"; + } else { //cookie not present + if (isNotEmpty(data.msclkidQuery) || msquery()) { + clickid = (isNotEmpty(data.msclkidQuery) || msquery()); + setUETCookie(clickid); + clickid += "-1"; + } else { + clickid = "N"; + } + } +} else { + if (isNotEmpty(data.msclkidQuery) || msquery()) { + clickid = (isNotEmpty(data.msclkidQuery) || msquery()); + setUETCookie(clickid); + clickid += "-1"; + } else { + if(isNotEmpty(data.msclkidCookie) || isNotEmpty(getCookieValues('_uetmsclkid'))){ + let clickid_cookie = getCookieValues('_uetmsclkid')[0]; + clickid = (isNotEmpty(data.msclkidCookie) || (clickid_cookie.substring(4))); + clickid += "-0"; + } else { + clickid = "N"; + } + } +} + + +const screen = data.screen || getEventData('screen_resolution'); + +let width, height = ""; +if (isNotEmpty(screen)){ + width = screen.split('x')[0]; + height = screen.split('x')[1]; + +} +let rn = generateRandom(100000, 999999); +function s4() { + return Math.floor(((1 + (generateRandom(1, 9999999)/10000000))) * 65536) + .toString(16) + .substring(1); +} + +let mid = (s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4()); +let items_data; +if(isNotEmpty(getEventData('items'))){ + items_data = getEventData('items'); +} + +let items = () => { + let result = ""; + if(isNotEmpty(data.prodid)){ + items_data = data.prodid; + } + if (data.itemsGa) { + if(items_data) { + items_data.forEach(function(item, i) { + result += "id=" + item.item_id + 'quantity=' + item.quantity + 'price=' + item.price; + if (i < items_data.length - 1) { + result += ','; + } + }); + } + } else { + result = items_data; + } + return result; +}; + + +let items_id = () => { + let result = ""; + if(isNotEmpty(data.items)){ + items_data = data.items; + } + if(data.prodidGa) { + if (items_data) { + items_data.forEach(function(item, i) { + result += item.item_id; + if (i < items_data.length - 1) { + result += ','; + } + }); + } + } + return result; +}; + +let spa = () => { + if(data.spa) { + return "Y"; + } else { + return "N"; + } +}; + +let params = { + rn: rn, + ti: data.ti, + ver: '2.3', + mid: mid, + uid: isNotEmpty(data.userId) || getEventData('user_id'), + evt: data.evt, + p: getEventData('page_location'), + r: getEventData('page_referrer'), + tl: isNotEmpty(data.pageTitle) || getEventData('page_title'), + pagetype: data.pagetype, + items: items(), + prodid: items_id(), + search_term: isNotEmpty(data.searchTerm) || getEventData('search_term'), + transaction_id: isNotEmpty(data.transactionId) || getEventData('transaction_id'), + lg: isNotEmpty(data.lg) || getEventData('language'), + sw: width, + sh: height, + sc: data.sc || getEventData('screen_color_depth'), + spa: spa(), + msclkid: clickid, + sid: isNotEmpty(data.sid) || getEventData('uet_session_id'), + vid: isNotEmpty(data.vid) || getEventData('vid'), + page_path: isNotEmpty(data.pagePath) || getEventData('page_path'), + gc: getEventData('currency'), + gv: getEventData('value'), + ec: isNotEmpty(data.ec) || getEventData('event_category'), + ea: isNotEmpty(data.ea) || getEventData('event_action'), + el: isNotEmpty(data.el) || getEventData('event_label'), + ev: isNotEmpty(data.ev) || getEventData('event_value'), +}; + + +if (data.activateLogs) { + logToConsole("Params: " + JSON.stringify(params)); +} + + +let url = 'https://bat.bing.com/action/0?'; +let all_params = ""; +if(isNotEmpty(params)){ + for (var key in params){ + if (params[key] == undefined || params[key] == null) { + continue; + } + all_params += key + "=" + encodeUriComponent(params[key]) + "&"; + } + url += all_params; +} +if (data.activateLogs) { + logToConsole('URL: ' + url); +} + + +return sendHttpGet(url, { + headers: {key: 'value'}, + timeout: 500, +}).then((result) => { + if (result.statusCode >= 200 && result.statusCode < 300) { + logToConsole('Result: ' + data.gtmOnSuccess()); + data.gtmOnSuccess(); + } else { + logToConsole('Error: ' + result.statusCode); + data.gtmOnFailure(); + } +}); diff --git a/pkg/tagmanager/web/trigger/builtin.go b/pkg/tagmanager/web/trigger/builtin.go index 343c782..a497ada 100644 --- a/pkg/tagmanager/web/trigger/builtin.go +++ b/pkg/tagmanager/web/trigger/builtin.go @@ -1,3 +1,6 @@ package trigger -const IDInitialization = "2147479573" +const ( + IDInitialization = "2147479573" + IDConsentInitializtion = "2147479572" +) diff --git a/pkg/tagmanager/web/variable/datalayervariable.go b/pkg/tagmanager/web/variable/datalayervariable.go index 453a4ac..8010bd4 100644 --- a/pkg/tagmanager/web/variable/datalayervariable.go +++ b/pkg/tagmanager/web/variable/datalayervariable.go @@ -25,7 +25,7 @@ func NewDataLayerVariable(name string) *tagmanager.Variable { { Key: "name", Type: "template", - Value: "eventModel." + name, + Value: name, }, }, Type: "v", diff --git a/pkg/typescript/imports.go b/pkg/typescript/imports.go index 54384ec..ecf2c47 100644 --- a/pkg/typescript/imports.go +++ b/pkg/typescript/imports.go @@ -31,6 +31,6 @@ func (i *Imports) Import(location string) *Import { func (i *Imports) Write(f *code.Section) { for key := range i.imports { - f.Sprintf(i.imports[key].String()) + f.Sprint(i.imports[key].String()) } } diff --git a/pkg/utils/contemplate.go b/pkg/utils/contemplate.go index a7e8e8f..c7d2e23 100644 --- a/pkg/utils/contemplate.go +++ b/pkg/utils/contemplate.go @@ -9,13 +9,13 @@ import ( "github.com/stoewer/go-strcase" ) -func LoadEventParams(cfg contemplate.Config) (map[string][]string, error) { +func LoadEventParams(cfg contemplate.Config) (map[string]map[string]string, error) { parser, err := contemplate.Load(&cfg) if err != nil { return nil, err } - ret := map[string][]string{} + ret := map[string]map[string]string{} for _, cfgPkg := range cfg.Packages { pkg := parser.Package(cfgPkg.Path) for _, typ := range cfgPkg.Types { @@ -30,18 +30,28 @@ func LoadEventParams(cfg contemplate.Config) (map[string][]string, error) { return ret, nil } -func getEventParams(obj types.Object) ([]string, error) { - var ret []string +func getEventParams(obj types.Object) (map[string]string, error) { + ret := map[string]string{} if eventStruct := assume.T[*types.Struct](obj.Type().Underlying()); eventStruct != nil { for i := range eventStruct.NumFields() { if eventField := eventStruct.Field(i); eventField.Name() == "Params" { if paramsStruct := assume.T[*types.Struct](eventField.Type().Underlying()); paramsStruct != nil { for j := range paramsStruct.NumFields() { - tag, err := ParseStructTagName(paramsStruct.Tag(j)) + var name string + var value string + + tag, err := ParseStructTagName(paramsStruct.Tag(j), "json") if err != nil { return nil, errors.Wrapf(err, "failed to parse tag `%s`", paramsStruct.Tag(j)) } - ret = append(ret, tag) + name = tag + value = "eventModel." + tag + + // check if there is a custom dlv tag + if tag, err := ParseStructTagName(paramsStruct.Tag(j), "dlv"); err == nil { + value = tag + } + ret[name] = value } } } diff --git a/pkg/utils/structtag.go b/pkg/utils/structtag.go index d34d8ca..c702510 100644 --- a/pkg/utils/structtag.go +++ b/pkg/utils/structtag.go @@ -6,31 +6,13 @@ import ( "github.com/fatih/structtag" ) -func ParseStructTagName(value string) (string, error) { +func ParseStructTagName(value, key string) (string, error) { tags, err := structtag.Parse(strings.Trim(value, "`")) if err != nil { return "", err } - tag, err := tags.Get("json") - if err != nil { - return "", err - } - - if tag.Value() != "" && tag.Value() != "-" { - return strings.Split(tag.Value(), ",")[0], nil - } - - return "", nil -} - -func ParseStructTagOmitempty(value string) (string, error) { - tags, err := structtag.Parse(strings.Trim(value, "`")) - if err != nil { - return "", err - } - - tag, err := tags.Get("json") + tag, err := tags.Get(key) if err != nil { return "", err } diff --git a/test/tagmanager/client_test.go b/test/tagmanager/client_test.go index d97f503..37e5c31 100644 --- a/test/tagmanager/client_test.go +++ b/test/tagmanager/client_test.go @@ -104,18 +104,17 @@ func TestNewClient_Server(t *testing.T) { }) } - { // --- Tags --- + { // --- Templates --- // t.Run("upsert template", func(t *testing.T) { // obj, err := c.UpsertCustomTemplate(template2.NewConversionsAPITag("Facebook")) // require.NoError(t, err) // dump(t, obj) // }) - t.Run("list templates", func(t *testing.T) { cmd := c.Service().Accounts.Containers.Workspaces.Templates.List(c.WorkspacePath()) if r, err := cmd.Do(); assert.NoError(t, err) { // dump(t, r) - fmt.Println(r.Template[0].TemplateData) + fmt.Println(r.Template[4].TemplateData) } }) } @@ -370,6 +369,16 @@ func TestNewClient_Web(t *testing.T) { // t.Log("ID: " + obj.TagId) // }) } + + { // --- Templates --- + t.Run("list templates", func(t *testing.T) { + cmd := c.Service().Accounts.Containers.Workspaces.Templates.List(c.WorkspacePath()) + if r, err := cmd.Do(); assert.NoError(t, err) { + // dump(t, r) + fmt.Println(r.Template[0].TemplateData) + } + }) + } } // ------------------------------------------------------------------------------------------------