En stor del af Tracking modulets ansvar er at holde styr på hvilke tracking moduler's kald skal være aktive.
Disse settings bliver oprettet automatisk med default på true. Det er vigtigt at hvis man har trackers som sender data videre, fx google tag manager som sættes op til at sende data videre til andre tracking sites, at slå den direkte forbindelse fra hos os. Ellers vil data dukke op dobbelt, fra os, og igennem GTM i dette exempel.
Settings er delt op i modul navn, kald navn, og hvorvidt kaldet er aktivt eller ej.
Herunder vil jeg liste de Client Events som vi på nuværende tidspunkt har i platformen, og deres data struktur.
{
"id": "0",
"name": "someProductName",
"price": "0.00",
"brand": "someBrandName",
"category": "someCategory"
}
{
"is_new": true,
"is_removed": false,
"quantityChange": 2,
"total_price": 13.37,
"variant": "someVariant",
"acquisition": 0.00,
"product_title": "someTitle",
"product_id": 42,
"item_count_before": 0
}
is_new fortæller os om kurven allerede indeholder productet eller ej. is_removed fortæller os om productet er fuldstændigt fjernet fra kurven. Event bliver brugt både når man tilføjer eller fjerner producter fra kurven.
{
"products": [
{
"name": "someProductTitle",
"id": "42",
"price": "13.37",
"variant": "someVariantenProperties",
"quantity": 2,
"aquisitions": "0.00"
}
],
"currency": "someCurrencyUsually_DKK"
}
Både i piranya-shop-checkout-initiated og piranya-shop-purchase-success er products en liste af alle producter og rabater. Rabaterne bliver sat ind med negativ værdi, og altid quantiy 1, og tom variant og tom acquisitions. En ting at notere er at vi på nuværende tidspunkt ikke har regnet den fulde rabat ud, og derfor ikke kan sende den med.
{
"id": "orderIdFx_42",
"transactionId": "siteIdentifierAndOrderIdFx_PS42",
"affiliation": "ourSiteIdentifierFX_PS",
"revenue": "0.00",
"tax": "0.00",
"shipping": "0.00",
"coupon": "someCoupon",
"currency": "someCurrencyUsually_DKK",
"products": [
{
"name": "someProductTitle",
"id": "42",
"price": "13.37",
"variant": "someVariantenProperties",
"quantity": 2,
"aquisitions": "0.00"
},
{
"name": "someRebateIdFx_2",
"id": "someRebateIdFx_2",
"price": "-5.20",
"variant": "",
"quantity": 1,
"aquisitions": ""
}
]
}
See evt piranya-shop-checkout-initiated for en beskrivelse af products.
Server events er sendt fra platformen, og bør håndteres, og videresendes fra platformen i egne moduler. Vi har mange server events, men dem som er blevet refactored/checked til at kunne blive brugt til tracking er de følgende:
Genralt så sender vi kun bestemte paramtre med hvis de er der, så strukturen vi viser her, kan i praktis sagtens mangle bestemte parametre. Fx i product_details_viewed vil vi i mange tilfælde ikke sende email med hvis vi ikke har den på det tidspunkt.
{
"productId" : "42",
"long_userId" : "42.0",
"dateTime" : "dateTimeObject",
"email" : "someUser@email.com",
"userIpAddress" : "192.168.1.1",
"userAgent" : "someUserAgent"
}
Noter at long_userId er en long værdi.
{
"productId" : "1337",
"aquisitions" : "0.00",
"currency" : "someCurrencyCodeFX_DKK",
"value" : "2.00",
"amount" : "7",
"totalValue" : "14.00",
"userId" : "42",
"dateTime" : "someDateTimeObject",
"email" : "someUser@email.com",
"userIpAddress" : "192.168.1.1",
"userAgent" : "someUserAgent"
}
{
"orderId" : "1337",
"sessionId" : "someSessionId",
"email" : "someUser@email.com",
"userId" : "42",
"customerId" : "420",
"dateTime" : "someDateTimeObject",
"userIpAddress" : "192.168.1.1",
"userAgent" : "someUserAgent"
}
{
"status" : "OrderStatus.PaymentCaptured",
"order_id" : "42",
"userIpAddress" : "192.168.1.1",
"userAgent" : "someUserAgent",
"time" : "aDateTimeObject"
}
Dette event bliver brugt en del i shop modulet, og indeholder ikke nødvendigvis det samme data i alle kald. Hvad vi har beskrevet er specifikt for OrderStatus.PaymentCaptured, hvilket kan blive brugt til purchase events. Desuden så kan keyen "order_id", også hede "orderId" eller blive gemt som et fuldt order object under navnet "order".
Google Tag Manager er et gratis værktøj, der gør det nemt for udviklere at administrere og deployere marketing tags(små stykker kode eller tracking pixels) på et website uden at skulle ændre selve websitets kode. Med GTM kan brugere oprette tags, definere trigger regler for hvornår disse tags skal aktiveres, og sætte variabler der kan ændres dynamisk. Det er med til at strømline processen og øge hastigheden på website performance, samtidig med at det øger nøjagtigheden i datatracking.
Det er her vigtigt at vide at hvis man sætter google tag manager(GTM) op til at håndtere beskeder som så bliver sendt viderer til en anden service, skal man slå den service fra i piranya, eftersom de tracking apier ikke nødvendigvis håndtere duplikat beskeder godt, eller overhovedet.
For at modtage data på GTM skal man havde sat Triggers og Variables op.
For at sende dataen videre skal man havde sat Tags op.
"tags" refererer her til små stykker kode, der er tildelt en specifik funktion eller formål. Typisk er tags designet til at indsamle data fra en hjemmeside og sende disse data til tredjeparter. Disse tredjeparter kan være forskellige online markedsførings- og analyseværktøjer som Google Analytics, Facebook Pixel, AdWords osv.
Et tag kan for eksempel være et sporingstag, der indsamler oplysninger om brugerinteraktioner på en hjemmeside, såsom klik på knapper, formularindsendelser, eller sidevisninger, og sender disse data til en analysetjeneste. Andre tags kan være designet til at udløse specifikke hændelser, som at vise en popup eller ændre et element på en side.
Tags implementeres på en hjemmeside ved hjælp af Google Tag Manager, som tillader nem og centraliseret administration af tags. I stedet for at skulle indkode hvert tag manuelt i hjemmesidens kildekode, kan man med GTM oprette og ændre tags via et brugervenligt interface.
"triggers" er her de regler, der bestemmer, hvornår et specifikt tag skal fyres. En trigger kan være baseret på en række forskellige hændelser, som f.eks. visning af en side, klik på et link, formularindsendelser, eller skræddersyede hændelser. Når en defineret hændelse sker på et website, og betingelserne i en trigger er opfyldt, vil det tilsvarende tag blive aktiveret. Triggers gør det muligt at kontrollere, hvornår og under hvilke omstændigheder tags skal fyres.
"variabler" er her informationselementer, der kan bruges til at dynamisk ændre eller tilpasse tags og triggers. De kan indeholde data, der er indsamlet fra brugerinteraktioner, miljødata eller andre informationer fra websitet. Variabler kan fx bruges til at definere, hvornår et bestemt tag skal aktiveres (trigger), eller til at tilpasse det data, der sendes med et tag. De gør GTM fleksibelt og kraftfuldt ved at tillade mere dynamisk og tilpasset tagimplementering.
I Google Tag Manager arbejder variabler, triggers og tags tæt sammen for at muliggøre dynamisk dataindsamling og -styring.
"Tags" er stykker af kode, der udfører specifikke opgaver, som f.eks. at indsamle data eller udløse en hændelse på en hjemmeside. For at et tag skal kunne udføre sin opgave, skal det vide hvornår og hvordan det skal gøre det.
Her kommer "triggers" og "variabler" i spil. En "trigger" er en regel, der fortæller et tag, hvornår det skal aktiveres. Dette kan være baseret på brugerinteraktioner eller andre hændelser på hjemmesiden.
"Variabler" er elementer, der indeholder specifikke data eller oplysninger. De kan bruges til at tilpasse, hvordan og hvornår et tag fyres. For eksempel kan en variabel indeholde information om den aktuelle side-URL, og denne information kan bruges i en trigger til at bestemme, om et specifikt tag skal aktiveres.
Man skal opsætte variabler så man kan kæde den data sammen som man modtager og de tags man opretter.
Her skal man vælge "Data Layer Variable" som variablens type.
"Data Layer Variable Name" er hvor det bliver en smule complekst. Det skal være den værdi fra en besked som man gerne vil gemme ned i dot-notation, hvilket betyder for hvert niveau man skal ned, skal man ligge et punktum imellem.
fx hvis man har datasættet
{
"event": "eec.detail",
"ecommerce": {
"detail": {
"products": [{
"brand": "brandButIsOnlyHereIfThereIsABrand",
"category": "CategoryOfTheProductIfTheProductHasACategory",
"id": 5,
"name": "SomeProductName"
}]
}
}
}
og man gerne vil gemme name ned i en variable, så skal man sætte "Data Layer Variable Name" til "ecommerce.detail.product.0.name" uden """. Læg mærke til 0, som er en del af navnet. Det er fordi i datasætet indikere "[]" en liste, og 0 det første element. Man kan også gemme et json object til at sende videre, fx hvis man gerne vil gemme products, så skal man bare istedet gemme "ecommerce.detail.product".
Trigger Event navne på skrivende stund: addToCart, eec.checkout, eec.detail, eec.purchase, removeFromCart
Tags afhænger meget af hvad man kobler op imod. Det er stortset umuligt at lave en generel guide. De fleste store spillere har Tag Configuration Templates som man kan gøre brug af. Og er det en forbindelse internt i google, er der helt sikkert en template til det. Her bør man opsøge documentation for hvad man integrere med. Jeg vil dog ligge et eksempel her på hvordan man opretter en Custom HTML tag, som så vil eksekvere html koden, som kan indeholde et normalt html-script-tag og derved eksekvere en funktion. Det ville kunne bruges i mange tilfælde hvor et template ikke er tilstede, eller kendt.
Et exempel på html-kode:
<script>
fbq('track', 'AddToCart', {
value: '{{Add_Product_price}}',
currency: 'DKK',
content_ids: '{{Add_Product_id}}',
content_type: 'product',
aquisitions: '{{Add_Proudct_Acquisitions}}',
content_name: '{{Add_Product_name}}',
num_items: '{{Add_Product_quantity}}'
}, {
eventID: '{{Event_id}}'
});
</script>
I eksemplet bliver forskelige Variabler brugt via {{}}. Dette eksempel vil sende et FacebookPixel event afsted til Facebook.
Vi har følgende kald som vi bruger med GTM
I de følgende afsnit viser vi hvordan dataen er konstrueret, samt en kort beskrivelse af hvad den logisk indeholder.
{
"event": "eec.detail",
"ecommerce": {
"detail": {
"products": [{
"brand": "brandButIsOnlyHereIfThereIsABrand",
"category": "CategoryOfTheProductIfTheProductHasACategory",
"id": 5,
"name": "SomeProductName"
}]
}
}
}
ViewContent er de sider som indeholder information om et product. Ikke alle hjemmesider er sat op med denne type information.
{
"event": "addToCart",
"ecommerce": {
"currencyCode": "DKK",
"add": {
"products": [
{
"name": "SomeProductName",
"id": 42,
"price": 100.00,
"variant": null,
"acquisitions": 0,
"quantity": 2
}
]
},
"remove": {
"products": []
}
}
}
AddToCart er når et product bliver tilføjet til kurven. Den indeholder informationer omkring det product der bliver tilføjet med varianter mm.
{
"ecommerce": {
"event": "removeFromCart",
"currencyCode": "DKK",
"add": {
"products": []
},
"remove": {
"products": [
{
"name": "SomeProductName",
"id": 42,
"price": 100.00,
"variant": null,
"acquisitions": 0,
"quantity": 2
}
]
}
}
}
RemoveFromCart er en modsætning til AddToCart i det at det er når et product bliver fjernet fra kurven. Indeholder den samme information som AddToCart gør, men ligger det i "remove"
{
"event": 'eec.checkout',
"ecommerce": {
"checkout": {
"actionField": {
"step": 1
},
"products": [
{
"name": "Sandwich",
"id": 51,
"price": 20,
"variant": "Varianter: Test1",
"quantity": 2
},
{
"name": "SomeMinorItem",
"id": 5206,
"price": 2,
"variant": "",
"quantity": 1
}
]
}
}
}
InitiateCheckout er når en bruger lander på checkout siden, men ikke har betalt endnu. Kan fx bruges til at håndtere forladte kurve.
Noter at rabater ikke er udregnet her, så de er ikke medregnet i Checkout.
{
"event": "eec.purchase",
"ecommerce": {
"currency": "DKK",
"purchase": {
"actionField": {
"id": 1,
"affiliation": "AAA",
"revenue": 42.00,
"tax": 9.00,
"shipping": 25.00,
"coupon": "SomeStringThatIsTheCouponTokenFx_KjI0LDpDenj67",
"currency": "DKK"
},
"products": [
{
"name": "Sandwich",
"id": 51,
"price": 20,
"variant": "Varianter: Test1",
"quantity": 2
},
{
"name": "SomeMinorItem",
"id": 5206,
"price": 2,
"variant": "",
"quantity": 1
}
]
}
}
}
Purchase sker når et køb er gået igennm. Den indeholder informationer om hvad der er blivet købt, samt salgs informationer.
Facebook Conversions er facebooks server api for deres pixel. Dvs at vi kan herigennem sende data direkte fra vores platform til facebook pixel. Det har en del fordele, fx så er det en hel del mere reliable i det at man kan garantere at beskederne bliver sendt, og ved fejl sende igen. Derudover så kan vi sende data som man ikke ville havde tilgængelig på clienten, og sende det krypteret. Her har facebook fx lagt op til at sende bruger data. I forhold til nogle af de andre api'er så er Facebook conversion lidt mere kræsen med hvordan dens data ser ud, og man skal sætte det op på den pixel man vil havde det til at køre med, med den samme struktur som vist her.
All følsom userdata bliver encryptet. Exemplerne givet her er fra en test maskine, og faktisk data sendt og modtaget.
Det er også vigtigt at nævne at for at få det sat op skal man generere en access token fra eventManger i facebook buisness manageren. Det skyldes at facebook conversions ikke udnytter samme flow som andre facebook services, og ikke gør brug af deres normale authentication. Det er dog rimelig let at genererer. Derefter er det også vigtigt at sætte op de kald som man vil modtage i facebook. Samme sted som man genererer token er der en step-by-step guide til at tilføje events som facebook herefter lytter efter. Her er det vigtigt at de følgende events, og de parametre som er givet i custom_data er inkluderet.
{
"data": [
{
"event_name": "ViewContent",
"event_time": 1631189391.0,
"action_source": "other",
"user_data": {
"external_id": [
"0dbd790fbbe427751bb1146aa0b071db2cfd327770290357c41f882216bf6ad3"
],
"em": [
"864adde25a5c0fc683a2b7ee5e48b367b64c190c4a49bd8497e979a0820f5b72"
],
"ph": [
"c910d45e9935185ba46e641c3ce1161ba6ee55458df415d1a9cda2cb5817c071"
],
"fn": "d25949ef9e762fe7cfb9cc5d125e8a7bbca56662abc51b9d0dc0d2265aa28dce",
"ln": "f170d9c0dc102cee8342fb734e2a41e29382e3ff88e4bf1a0fece2031644291b",
"ct": "8557efaa71498248fa2309cbd3b42e188ed86152a819b6cc2e88da8c5e099454",
"zp": "7114a0882e5d0d63aba8d73cbf0f5a36201948eb24f5c49296a4ee5e0b6d0963",
"client_ip_address": "::1",
"client_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
},
"custom_data": {
"content_ids": [
50
],
"content_type": "product"
}
}
]
}
{
"data": [
{
"event_name": "AddToCart",
"event_time": 1631189441.0,
"action_source": "other",
"user_data": {
"client_ip_address": "::1",
"client_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
},
"custom_data": {
"content_ids": 50,
"content_type": "product",
"aquisitions": 0.0,
"currency": "DKK",
"value": 1.0
}
}
]
}
{
"data": [
{
"event_name": "InitiateCheckout",
"event_time": 1631189470.0,
"action_source": "other",
"user_data": {
"external_id": [
"0dbd790fbbe427751bb1146aa0b071db2cfd327770290357c41f882216bf6ad3"
],
"em": [
"864adde25a5c0fc683a2b7ee5e48b367b64c190c4a49bd8497e979a0820f5b72"
],
"ph": [
"c910d45e9935185ba46e641c3ce1161ba6ee55458df415d1a9cda2cb5817c071"
],
"fn": "d25949ef9e762fe7cfb9cc5d125e8a7bbca56662abc51b9d0dc0d2265aa28dce",
"ln": "f170d9c0dc102cee8342fb734e2a41e29382e3ff88e4bf1a0fece2031644291b",
"ct": "8557efaa71498248fa2309cbd3b42e188ed86152a819b6cc2e88da8c5e099454",
"zp": "7114a0882e5d0d63aba8d73cbf0f5a36201948eb24f5c49296a4ee5e0b6d0963",
"client_ip_address": "::1",
"client_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
},
"custom_data": {
"content_ids": [
50
],
"content_type": "product"
}
}
]
}
Noter at rabater ikke er udregnet her, så de er ikke medregnet i Checkout.
{
"data": [
{
"event_name": "Purchase",
"event_time": 1631189528.0,
"action_source": "other",
"user_data": {
"em": [
"307d9a24688943fcce8fdcee81759d35a6fb8115806a1d9beab8d4a24f8cdf35"
],
"ph": [
"ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f"
],
"fn": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25",
"ln": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25"
},
"custom_data": {
"currency": "DKK",
"value": 1.0,
"contents": [
{
"id": 50,
"item_price": 1.0,
"quantity": 1
}
]
}
}
]
}
Facebook pixel er vores implementering der sender direkte til pixel fra clienten. Vi anbefaler at bruge google tags hvor muligt, men er dette ikke en mulighed har vi denne implementering.
{
"id": 42,
"name": "someProductTitle",
"brand": "someBrandName",
"category": "someCategoryName",
"value": 42
}
{
"name": "someTitle",
"id": 42,
"price": 0.00,
"variant": "someVariant",
"acquisitions": 0.00,
"quantity": 7
}
{
"name": "someTitle",
"id": 42,
"price": 0.00,
"variant": "someVariant",
"acquisitions": 0.00,
"quantity": 7
}
{
"content_type": "product",
"currency": "someCurrencyUsually_DKK",
"value": 0.00,
"contents": [
{
"name": "someProductName",
"id": 43,
"quantity": 7,
"item_price": 5.20,
"variant": "someProductVariant",
"aquisitions": 0.00
},
{
"name": "someOtherProductName",
"id": 44,
"quantity": 7,
"item_price": 5.20,
"variant": "someProductVariant",
"aquisitions": 0.00
}
]
}
mht contents så følger det samme logik som i [Google Tag Manager]'s InitiateCheckOut. Noter at rabater ikke er udregnet her, så de er ikke medregnet i Checkout.
{
"currency": "someCurrencyCodeFX_DKK",
"content_type": 'product',
"id": "siteIdentifierAndOrderIdFX_PS42",
"value": 0.00,
"tax": 0.00,
"shipping": 0.00,
"coupon": "someCoupon",
"affiliation": "someAffiliation",
"contents": [
{
"name": "someProductName",
"id": 43,
"quantity": 7,
"item_price": 5.20,
"variant": "someProductVariant",
"aquisitions": 0.00
},
{
"name": "someOtherProductName",
"id": 44,
"quantity": 7,
"item_price": 5.20,
"variant": "someProductVariant",
"aquisitions": 0.00
}
]
}
mht contents så følger det samme logik som i [Google Tag Manager]'s InitiateCheckOut.