File PDF .it

Condividi facilmente i tuoi documenti PDF con i tuoi contatti, il Web e i Social network.

Inviare un file File manager Cassetta degli attrezzi Assistenza Contattaci



Dev GTM guide v3 7 .pdf



Nome del file originale: Dev - GTM guide v3_7.pdf

Questo documento in formato PDF 1.5 è stato generato da Microsoft® Word 2010, ed è stato inviato su file-pdf.it il 17/03/2015 alle 10:53, dall'indirizzo IP 93.62.x.x. La pagina di download del file è stata vista 3435 volte.
Dimensione del file: 4.5 MB (99 pagine).
Privacy: file pubblico




Scarica il file PDF









Anteprima del documento


ClientDomain.com

"Generic" GTM Developer Guide
ID: ClientDomain_GTM_Dev_Guide_v4.86
Author: Phil Pearce
Date: 11th March 2015
Please download the latest version of this document
here: bit.ly/gtmdevguide2
or its GTM for App`s companion bit.ly/gtmappguide2
If you have suggestions for improving this document please email:
phildpearce@gmail.com
Many Thanks!
Phil Pearce
Senior Web Analyst
phildpearce@gmail.com
http://uk.linkedin.com/in/philpearce
Demo GTM account login to accompany this guide;
login: coolgtmstuff@gmail.com (read-only login)
pw: philrulesgtm2
Change Log:
th
1. Updated process tree on pg4 [PP on 16 Sept 2013]
rd
2. Added auto-event PDF download, mailto & outbound link tracking [PP on 3 Oct]
th
3. Added brandName,country,region,externalCrossDomainlinksToDecorate to dataLayer [PP 5 Oct]
th
4. Added "growth of GTM page" [PP on 6 Oct 2013]
th
5. Added gtm.whitelist and gtm.blacklist [PP on 20 Oct 2013]
nd
6. Added position of GTM on the page [PP on 2 Nov 2013]
th
7. Added remarketing example [PP 9 Dec 2013]
8. Updated CustomDimensions with userScope=6months, sessionScope=30mins, pageScope=pageOnly (e.g.
isNewRegistration // cd[n]_userScope) and pageGrouping with appended variableName (e.g.
th
pageGroup[n]_category) [PP on 18 Dec 2013]
th
9. Updated W3C digitalData dataLayer Names spec [PP on 18 Dec 2013]
th
10. Added tip about seamless migration of old code into GTM customHTML using an event. [16 Jan]
th
11. Added video tracking examples and window.dataLayer = window.dataLayer || []; [PP 17 Jan]
th
12. Added Dedduracell Tomi`s WordPress plugin [PP 24 Jan 2013]
th
13. Added gtm.pageError (this works like jslogger.com or muscula.com) [PP 21 Feb]
rd
14. Added gtm.historyChange reference [PP 23 March]
th
15. Added note about jQuery vs auto-events in planning phase [PP 12 April]
16. IMPORTANT: Reserved pageGroup5 & page level customDimension5 for {{autoContainerVersion}}. If "not
set" it reveals legacy GA code that has not been deployed via GTM (i.e. Quality Assurance testing).
th
17. Added migration from GA to GTM steps [PP 22 April]
th
18. Added cascading lookup tables for GA accountID [PP 24 April]
19. IMPORTANT: following fierce debate & feedback; updated most variableNames to camelCase (e.g.
th
transactionId) and added section about naming conventions [PP 25 April]
th
20. Updated GTM market share report on page3. [PP 3 May]
th
21. Added tag scanning and tag mapping section [PP 3 May]
th
22. Updated list of installation questions and common mistakes. [PP 3 May]
th
23. Added straight and parallel GA classic to GTM universal deployment process steps. [PP 4 May]
24. Updated transactionPromoCode to transactionCoupon, added transactionType and firstPurchaseDate to
th
determine customer Age. Added event:"transaction" [PP 5 May]
25. Moved customDimension 15-20 into dataLayer.google_tag_params & removed google_tag_params
26. Moved all customDimension except user_id & cart_id into dataLayer.google_tag_params nesting.
27. Updated universal analytics upgrade video here. Added warning & checklist about 3Dsecure for universal
1
ecommerce migrations.
28. IMPORTANT: Added process for determining thankyou page trigger method.
th
29. Added demo ecommerce website here with example dataLayer [PP 16 April].
th
30. Added GTM dataLayer names cheatsheet, and reasons for growth. Moved w3c list up in document [PP 30 June].
31. Added planning account structure for international websites section.

Contents
Foreword: Who is intended audience for this guide? ....................................................................4
Growth & adoption of GTM ......................................................................................................4
Reasons for Growth ...................................................................................................................5
Cheat sheet of #digitalData JSON Object Names (v1.0.1) ........................................................6
GTM DataLayer cheat sheet (Enhanced Ecommerce version v2.0) ..........................................7
GTM DataLayer cheat sheet (App version v1.0) .......................................................................8
Executive Summary .......................................................................................................................9
Installation Plan .......................................................................................................................10
Common GTM setup mistakes to avoid ..................................................................................11
Comparison of GA setup vs GTM setup..................................................................................13
Tag scanning & mapping: pre & post migration .....................................................................14
Installation Questions...............................................................................................................15
STRAIGHT deployment: GA classic to GTM migration ........................................................16
PARALLEL deployment: GA classic to GTM migration .......................................................17
Universal migrations: ecommerce 3Dsecure non-iframe referrals ..........................................18
Plugins vs custom coding.........................................................................................................20
Plugin: GTM for Magento .......................................................................................................20
Plugin: GTM for Wordpress & WooCommerce ......................................................................21
Plugin: GTM for Joomla ..........................................................................................................22
Planning account structure .......................................................................................................23
Position of the dataLayer and gtm.js ........................................................................................24
Planning the setup of development environment .....................................................................25
GTM-xxxx account ID for DEV and LIVE .............................................................................26
Cascading lookup tables for UA-xxxx-x .................................................................................27
Deciding on a thank you page trigger method .........................................................................28
Deciding on a rule trigger position (onload, onready or page footer) .....................................29
Seamless migration of Tags to GTM .......................................................................................30
Deciding on a dataLayer schema .............................................................................................31
Deciding on a dataLayer naming convention standard ............................................................32
Clean page mark-up and avoidance of use of inline code .......................................................33
jQuery vs GTM auto-events.....................................................................................................34
Logins & permissions ..............................................................................................................35
Debug process ..........................................................................................................................36
How to debug video .................................................................................................................36
Chrome Tag Assist Plugin - MUST be installed .....................................................................37
GTM scripts examples .............................................................................................................39
GTM configuration - dont use inline configuration .................................................................39
Adwords dynamic remarketing custom categories ..................................................................42
Ecommerce Transactions on sale complete pages ...................................................................43
Social Measurement: Social actions buttons............................................................................46
Item page tracking....................................................................................................................50
Inline page error tracking .........................................................................................................51
Modal and Ajax box tracking ..................................................................................................52
Manual Video tracking ............................................................................................................52
Onsite search ............................................................................................................................53
404 Error Tracking ...................................................................................................................54
Custom dimensions: Registered logged-in users .....................................................................55
Custom dimensions: Customer Groupings ..............................................................................55
Auto-event PDF & outclick tracking examples .......................................................................56
Auto-event JavaScript Error detection .....................................................................................62
List of QA test ..........................................................................................................................63
2

Appendix ......................................................................................................................................64
Links to other resources ...........................................................................................................64
Security checklist .....................................................................................................................65
More debugging tips: ...............................................................................................................66
GTM settings screenshot..........................................................................................................68
Note about Bing & Omniture document.write code ................................................................69
Plugin: Prevent GA ecommerce counting twice (Courtesy Brian Kuhn) ................................70
Plugin: Mapping Qubit dataLayer to GTM ecommerce dataLayer .........................................71
Plugin: Adwords Custom/Dynamic Remarketing ...................................................................74
Work-around for tag firing dependencies ................................................................................77
Plugin: CustomHTML fallback script for dc.js (legacy script) ...............................................78
Plugin: Civic cookie consent notification script ......................................................................79
GTM & Flash videos ...............................................................................................................80
GTM & iFrames .......................................................................................................................81
GTM & noscript tracking.........................................................................................................81
Map W3C names to GTM names - used to pass validation .....................................................86
Map W3C digitalData ecommerce to legacy GTM ecommerce ..............................................87
Map legacy GTM ecommerce >> new enhanced GTM ecommerce ......................................88
Map new enhanced GTM ecommerce >> legacy GTM ecommerce .......................................89
W3C digitalData.privacy meta data & serverResponseForDNT .............................................90
JSON-LD: One to watch for the future ....................................................................................91
Enhanced ecommerce process summary .................................................................................95
Release notes for Google Tag Manager ...................................................................................96

3

Foreword: Who is intended audience for this guide?
This guide was written based on the learnings from 15 enterprise level GTM installations. It is
designed for developers, analysts and project managers.
It assumes a basic level of knowledge of Google Analytics and JavaScript and covers a
summary of lessons learned; for specific examples please watch this video playlist.

Growth & adoption of GTM
GTM is rapidly being adopted and it is used by some of the largest websites on the internet.

Source: trends.builtwith.com/widgets/tag-management
& w3techs.com/technologies/history_overview/tag_manager

Only Adobe Dynamic Tag Manager (Satellite), Tealium and Mezzobit are growing - all other
TMS are remaining static or declining.

Source: trends.builtwith.com/widgets/Google-Tag-Manager

GTM is on 10% of all big websites - its usage has doubled in 12months.
4

Reasons for Growth
Tag management is an essential component of any tracking deployment. The most
common reason ns for why this is essential include:
1.
2.
3.
4.
5.

Agility & Control
Remarketing
Deployment Cost
Site Speed
Privacy

Moving to TMS - anticipated vs actual benefit compared
from June 2012 econsultancy survey
100%
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%

86%

81%

86% 84%

82%
68%

Marketing Agility
& Control

Remarketing

68%

61%

Deployment Cost

Considering TMS

76%
57%

Site Speed

Privacy

Using TMS

Source: econsultancy.com/reports/tag-management-buyers-guide

Marketing agility

Dependable data

Quick & easy

Add tags anytime
- no waiting

Get better insights
for smarter decisions

Simple for marketers, IT,
and agencies

Additionally, it standardises data capture, by using a common set of object names
across multiple websites. This significantly simplifies installations as generic
configuration files can be used (see next 2 pages)

5

Cheat sheet of #digitalData JSON Object Names (v1.0.1)
Page

Products

Cart

Transaction

page.pageInfo.pageID

product[n].productInfo.productID

cart.cartID

transaction.transactionID

page.pageInfo.pageName

product[n].productInfo.productName

cart.price.basePrice

transaction.total.basePrice

page.pageInfo.version

product[n].productInfo.description

cart.price.voucherCode

transaction.total.voucherCode

page.pageInfo.sysEnv

product[n].productInfo.manufacturer

cart.price.voucherDiscount

transaction.total.voucherDiscount

page.pageInfo.breadCrumbs

product[n].productInfo.size

cart.price.currency

transaction.total.currency

page.pageInfo.variant

product[n].productInfo.productImage

cart.price.taxRate

transaction.total.taxRate

page.pageInfo.destinationURL

product[n].productInfo.productThumbnail

cart.price.shipping

transaction.total.shipping

page.pageInfo.referringURL

product[n].productInfo.productURL

cart.price.shippingMethod

transaction.total.shippingMethod

page.pageInfo.onsiteSearchTerm

product[n].category.primaryCategory

cart.price.priceWithTax

transaction.total.priceWithTax

page.pageInfo.onsiteSearchResult

product[n].category.subCategory1

cart.price.cartTotal

transaction.total.transactionTotal

page.pageInfo.language

product[n].category.productType

transaction.attributes.paymentMethod

page.pageinfo.country

product[n].attributes.productSeason

cart.attributes.isProductBundle
Component (Widgets)

page.pageInfo.geoRegion

component[n].attributes.socialWidget
User (Profile & Segments)

transaction.item[n].productInfo.productName

page.pageInfo.issueDate

product[n].linkedProduct[n].productInfo
Events

page.pageInfo.effectiveDate

event[n].eventInfo.eventName

user.profile.profileInfo.profileID

transaction.item[n].productInfo.manufacturer

page.pageInfo.expiryDate

event[n].category.primaryCategory

user.profile.profileInfo.userName*

transaction.item[n].category

page.pageInfo.author

event[n].eventInfo.eventAction

user.profile.address*

transaction.item[n].price

page.pageInfo.publisher

event[n].eventInfo.type

user.profile.social.facebook*

transaction.item[n].quantity

page.pageInfo.industryCodes

event[n].eventInfo.eventPoints

user.profile.social.facebookInfo

page.category.primaryCategory

event[n].eventInfo.timeStamp

user.profile.social.twitter*

transaction.item[n].linkedProduct[n].productInfo
Transaction (Billing Address)

page.category.subCategory1

event[n].eventInfo.effect

user.profile.social.twitterInfo

transaction.profile.address.line1*

page.category.pageType

event[n].category.subCategory1

user.segment.isNewRegistration

transaction.profile.address.line2

page.attributes.numberOfComments
Version & Environment

event[n].attributes.nonInteractive

user.segment.isUserNewCustomer

transaction.profile.address.city

user.segment.isLoggedIn

transaction.profile.address.stateProvince

user.segment.customerClassDimension

transaction.profile.address.country

user.segment.visitorLifetimeValue

transaction.profile.address.postalCode*

version: (1.0)

Security & Privacy
cat1.cat2.cat3.security.variableName

pageInstanceID:(dev | staging | live) privacy.accessCategories[n].domains
6

transaction.item[n].productInfo.productID
transaction.item[n].productInfo.description

GTM DataLayer cheat sheet (Enhanced Ecommerce version v2.0)
Promotional Banner

Products

Cart

Transaction

ecommerce.promoClick.promotions[n].id

ecommerce.detail.products[n].id

ecommerce.add.actionField.id

ecommerce.purchase.actionField.id

ecommerce.promoClick.promotions[n].creative ecommerce.detail.products[n].name

ecommerce.add.actionField.step

ecommerce.purchase.actionField.step

Page

ecommerce.detail.products[n].brand

ecommerce.currencyCode

ecommerce.currencyCode

page.id

ecommerce.detail.products[n].variation

ecommerce.add.actionField.coupon

ecommerce.purchase.actionField.coupon

pageTitle

ecommerce.detail.products[n].category

ecommerce.add.actionField.couponDiscount

ecommerce.purchase.actionField.couponDis

pageVirtual

ecommerce.detail.products[n].price

ecommerce.add.actionField.tax

ecommerce.purchase.actionField.tax

pageDeviceSysEnv
pageDeviceOrientation

ecommerce.detail.products[n].position

ecommerce.add.actionField.shipping

ecommerce.purchase.actionField.shipping

ecommerce.detail.products[n].list

ecommerce.add.actionField.shippingMethod

ecommerce.purchase.actionField.shippingM

google_tag_params.session_testVariant

google_tag_params.ecomm_pagetype

ecommerce.add.actionField.subTotalIncludeTax

ecommerce.purchase.actionField.subTotalIn

pageSiteSearchTerm

google_tag_params.ecomm_prodid

ecommerce.add.actionField.revenue

ecommerce.purchase.actionField.revenue

pageSiteSearchResults

google_tag_params.ecomm_rec_prodid google_tag_params.ecomm_rec_prodid

ecommerce.purchase.actionField.paymentM

pageLanguage

Social Events

User (Profile & Segments)

ecommerce.purchase.actionField.date

pageCountry

socialNetwork

user.id

ecommerce.purchase.products[n].id

pageGeoRegion

socialAction

firstPurchaseDate

ecommerce.purchase.products[n].name

pageContentCreated

Events

visitorLifetimeValue

ecommerce.purchase.products[n].variation

google_tag_params.ecomm_pagetype

event

google_tag_params.isNewRegistration

ecommerce.purchase.products[n].brand

pageGroup2_category

eventCategory

google_tag_params.isUserNewCustomer

ecommerce.purchase.products[n].category

pageGroup3_subCategory

eventAction

google_tag_params.isLoggedIn

ecommerce.purchase.products[n].price

pageGroup4_templateName

eventLabel

google_tag_params.user_memberType

ecommerce.purchase.products[n].quantity

pageGroup5_containerVersion

eventValue

google_tag_params.user_ageRange

Transaction (Billing Address)

Version, Environment and Status

eventNonInteractive

google_tag_params.user_gender

ecommerce.purchase.actionField.city

version: (v2)

Security & Privacy

google_tag_params.user_customerQualityScore ecommerce.purchase.actionField.region

environmentIdentifier: (dev | staging | live)

2 stage authentication security setting

google_tag_params.user_highSpenderScore

ecommerce.purchase.actionField.country

event: header_datalayer_loaded

DoubleClick and GA opt-out privacy link

google_tag_params.session_type

ecommerce.purchase.actionField.postalRegi

Note: utm_id / campaignCode for marketing
campaign landing pages not mentioned.
7

GTM DataLayer cheat sheet (App version v1.0)
Screen
screen.id
screenName
screenDeviceSysEnv
screenDeviceOrientation
googleContentExperimentsVersion
screenSiteSearchTerm
screenSiteSearchCategories
screenSiteSearchResults
language
screenCountry
screenGeoRegion
google_tag_params.ecomm_pagetype
screenGroup2_category
screenGroup3_subCategory
screenGroup4_templateName
screenGroup5_containerVersion
referrer (Android only)
customFunction (JSON value triggers)
Version, Environment and Status
app name: (angry birds)
app id: (com.rovio.angrybirds)
app version: (4.2.1)
ga_debug: (on | off)
event: onload_datalayer

Products
ecommerce.detail.products[n].id
ecommerce.detail.products[n].name
google_tag_params.ecomm_pagetype
google_tag_params.ecomm_prodid
Promotional Banner
ecommerce.promoClick.promotions[n].id
ecommerce.promoClick.promotions[n].creative
Events
event.id
event
eventCategory
eventAction
eventLabel
eventValue
eventNonInteractive
engagementPoints
Privacy
advertising tracking enabled (DNT=true|false)
id for advertising (IDFA)
iosPersistentId / andriodPersistentId
device id (Android only)
Security
Sandboxed: worst case custom Image
2 stage authentication security setting

Suggested Event Names
onload_screenview
onload_screenview_loggedIn
onload_screenview_accountCreated
onload_screenview_confirmation
ontap_close
ontap_search
exception

Cart
ecommerce.add.actionField.id
ecommerce.add.actionField.step
ecommerce.currencyCode
ecommerce.add.actionField.revenue
Social Events
socialNetwork
socialAction
Elements/Components
element.id
elementClass
elementName
User (Profile & Segments)
user.id
firstInstallDate
visitorLifetimeValue
google_tag_params.isNewRegistration
google_tag_params.isUserNewCustomer
google_tag_params.isLoggedIn
google_tag_params.user_memberType
google_tag_params.user_ageRange
google_tag_params.user_gender
google_tag_params.user_customerQualityScore
google_tag_params.user_highSpenderScore
google_tag_params.session_type

Content experiments and GooglePlay account
need to be linked to GA to run A/B tests and
see GooglePlay store impressions.
Referral Reporting (Android only)
For old versions of the GTM SDK for Android
8
(pre-v3.0) an AndroidManifest.xml file needs
to be added. The latest version does this
natively.

Crash reporting
Exception & crash tracking need to be
manual added (or triggered via a custom
function tag).
"event": "exception"
"exceptionIsFatal": true,
"exceptionDescription": "app is drunk"

Transaction
ecommerce.purchase.actionField.id
ecommerce.purchase.actionField.step
ecommerce.currencyCode
ecommerce.purchase.actionField.coupon
ecommerce.purchase.actionField.tax
ecommerce.purchase.actionField.revenue
ecommerce.purchase.actionField.date
ecommerce.purchase.products[n].id
ecommerce.purchase.products[n].name
ecommerce.purchase.products[n].variation
ecommerce.purchase.products[n].category
ecommerce.purchase.products[n].price
ecommerce.purchase.products[n].quantity
Transaction (Billing Address)
ecommerce.purchase.actionField.city
ecommerce.purchase.actionField.region
ecommerce.purchase.actionField.country
ecommerce.purchase.actionField.postalReg
Device
platform
operating system version
sdk version (aka platform version)
device name
screen resolution

Executive Summary
Once the KPI`s document has been delivered, we can instruct the developer to install
& test these measurements on the development environment.
Business
Objectives
Workshop
Objectives >
KPI`s

Example
KPI`s Doc

Create

Recommend
Vendor
Solution

Deploy

•a container

•the "empty" container

•the website to what you want to track

Map

Dev Guide
Configure

•the container in GTM settings interface

Installation

•in debug & preview mode

Test

QA testing
Migrate

•by simultaneously removing hard
coded tags & publishing the container

Training

Analysis &
Optimisation

9

Installation Plan
In order to successfully implement GTM it is necessary to cover 9 planning steps.
Macro level - migration planning:
1.
2.
3.
4.
5.
6.
7.
8.
9.

Getting IT buy-in & determining client development resources
Review existing GA installation
Tactical planning
Technical planning
Conversion trigger planning
Naming conventions plan
Quality assurance process
Reducing human errors (IT dept on-boarding & training process)
Security planning on Google Account

These 9 steps are covered in the next sections. Additionally, the outcome of each
phase such as technical planning, could have micro phases. For example using
"parallel" deployment micro phases:
Micro level - deployment planning using a parallel tag:
1. Create empty GTM container and add the code to global header of ALL pages.
2. Deploy parallel deployment of Universal via GTM, with GA classic running via
hardcode.
3. Find & replace GA classic code with event called onload_ga_pageview.
4. Add ecommerce dataLayer to checkout thankyou page
5. Replace inline code gaq.push with equivalent dataLayer.push code and add
GTM event tags within GTM settings, so there is a seamless migration.
6. Add better dataLayer for product pages and user-interactions.

Create

Deploy

Map

Configure

Test

Migrate

• a container
• the "empty" container
• the website to what you want to track
• the container in GTM settings interface
• in debug & preview mode
• by simultaneously removing hard coded tags & publishing the container

Tip: A Google quick start implementation plan is shown here.

10

Common GTM setup mistakes to avoid
1. No allocated client development resources or IT buy-in, or IT dept on-boarding training process.
2. No tactical planning:
a. Is the client rolling-out on one domain first or all-in-one-go?
b. If one domain first is this blog or site-section first or all-in-one-go?
c. Is the client running in fast migration sprints or single monthly releases (e.g. global
header, then ecommerce page, then events & customVars)?
3. No technical planning:
a. Has position of GTM been confirmed - i.e. is adding code to top <body> tag a problem?
b. Are plugins or custom code going to be used to enabled GTM and dataLayer?
c. What scanners (if any) are going to be used pre and post migration?
d. Determine method for dynamically setting GA-xxxxx-x via lookup table for hostname or
GTM-xxxx.
4. No naming conventions plan:
a. DataLayer names are not consistent with fixed GTM ecommerce names or W3C names.
b. Not defaulting to camelCase capitalisation on dataLayer names (very common)
c. Not defaulting to lowercase dataLayer values (very common)
5. No QA planning process:
a. No separate GA accountID for Dev traffic and testing (UA-00000-2)
b. GTM code not previewed and debugged before publishing.
c. Chrome Tag Assist not used to debug
i. Unescaped commas & single quotations in dataLayer by developers.
ii. GTM placed in nested <div> OR in <head> causing IE7 bug. A patch of using a
blocking rule on customHTML fixes: navigator.userAgent matches RegEx
^.+ \(.*MSIE [7-8]\.0; .*\).*$

iii. GTM iframe placed in <head> rather than <body> causing IE warning.
iv. GTM.js added TWICE with the same dataLayer name causing gtm.dom conflicts.

11

6. Human errors (or lack of GTM training):
a. setDomainName dataLayer not present (or added via jsmacro in GA classic)
i. mixing setDomainName="www.clientdomain.com" & "clientdomain.com" which
are different cookie domain hashes.
ii. fallback value setDomainName=auto not enabled - causing
setDomainName=undefined tracking fail!
b. default blankTracker name not used. Causing AddThis, ShareThis, Disqus, Livefyre,
Optimizely, LiveChat to send GA UA-xxxxx-1 errors in GA classic.
c. dataLayer=[]; used in CustomHTML must be used to append, rather than override values.
See this discussion here. Hence use window.dataLayer = window.dataLayer || [];
dataLayer.push({"event": "value"});

d. Hardcode gaq.push used rather than dataLayer.push within customHTML.
e. Hardcode UA-00000-1 used in customHTML rather than {{settings_ga_id}}
f. Typos in setting_ga_id default (or lookup table not used), thus migrations from Dev to Live
break GA accountID.
g. default value entered for userId dataLayer rather than "undefined" or "" causing userId
profile view to fail.
7. Other less common issues
a. When using localCountryTrackers, the {{trackerName}} macro must be used in
customHTML, otherwise GA will trigger UA-xxxxx-1 errors.
b. Local currency field not-set in ecommerce localTracker:
ga('create','{{settings_ga_id}}',
{'name':'localCountryTracker'},'set','currencyCode','{{transactionCurrency}
}');

c. If using Content Experiments and cross-domain tracking ensure
<script>_udn = "{{dataLayer.settings_ga_setDomainName}}";</script> is added.
8. Poor security planning on the Google Account :
a. Password easy to guess via brute force
b. Two-stage SMS authentication not enabled
c. HTML failsafe switch
"gtm.blacklist":["customScripts","nonGoogleScripts","nonGoogleIframes","k"]
not used.

More tips to avoid mistakes here:
ï‚· Troubleshooting Tips by Jeff Sauer (jeffalytics.com)
ï‚· Get the dataLayer Right by Josh West (WebAnalyticsDemystified)
ï‚· Common pitfalls by Qubit.

12

Comparison of GA setup vs GTM setup
Review existing GA installation.
Current setup:

Planned setup:

Note: see page 20 to confirm position of GTM script container.

13

Tag scanning & mapping: pre & post migration
If custom inline tracking tags are in use for onclick events or video, or there are multiple
tags to migrate, or it is a publishing website which needs to maintain measurement
certification standards. Then... a tag mapping process is needed, to assess what (and
when) tags should be migrated to the TMS. This process assists in planning the firing
rules and pages these rules need to trigger on.
The tag scan should be done both before and after deployment to verify everything has
migrated correctly, and there are no instances of double firing code or missing pages. It
is also helpful to scan the first 1,000 pages on the QA environment, for a sample test.

Tip1: A blog post explaining the tag mapping process by taginspector.com is here.
Tip2: Cookie crawler database can be used for quick mapping checks:
ï‚·
ï‚·
ï‚·

http://cookiepedia.co.uk/website/www.healthcare.gov
http://nibbler.silktide.com/reports/www.healthcare.gov
http://builtwith.com/healthcare.gov

Tip3: Running a homepage speed test before and after an installation to confirm tags
are loading at same (or faster) by recording the pixel initialisation time and initialisation
step number and is also helpful. Here is an example:
ï‚·
ï‚·

http://www.webpagetest.org/result/140503_AM_GRP/
http://www.webpagetest.org/result/140503_AM_GRP/1/details/#request36

14

Installation Questions
1. Is this a New Installation and thus GA universal? If yes... Jump to Q2. If no... it is an
Existing GA Installation with historic GA classic data, then:
a. Has the account been auto-migrated to Universal processing already? You in settings
you will see "upgrade complete" or "start upgrade".
Only GA premium acconts have not be auto-migrated.
b. Is the client currently reliant on GA data? (or is an existing system such as Omniture
et-al being used primarily for business reporting)
c. Does the client need to integrate with widgets such as Google+, AddThis, ShareThis,
Disqus, Optimizely, LiveChat or PhoneCall tracking providers which currently only
support legacy GA.js
d. Is native GooglePlus button tracking needed (not native in GA universal yet).
e. Is urchin.js being migrated or just ga.js? The Urchin sessionisation counts are different
to GA universal calculation; hence parallel installation will be needed.
f. Is a local copy of utm.gif enabled for ABC publisher auditing using
_setLocalRemoteServerMode and _setLocalGifPath? (easier in GA Classic, but possible
via a custom script for Universal).
g. Is resetting of customVariables as they are translated to over to a new
customDimensions field a problem? (Both are stored, but historic comparisons are
trickier due to moving to the new customDimensions field).
h. Is custom code for reading GA client-side cookie values utmz or getVisitorCustomVar
(1); on form submission being used?
i. Is retaining returning visitor cookies a problem? (analytics.js will piggyback returning
GA classic utmx cookies on the first hit, unless legacyHistoryImport is disabled)
j. Is integration with offline CRM required? (universal only)
k. Does the client have a requirement to track multi-device journeys from registered
users who are logged-in from Website to logged-in within App, and is a userId exposed
on the login page? (universal only)
l. Is GTM for app part of the migration?
m. Is cross-domain or iframe tracking required (easier in Universal).
2. Are multiple currencies tracking within localCountryTracker needed for Adwords ROAS
reports? And is client planning to use rolled-up trackers or localCountryTracker?
3. Are any legacy analytics.js or ga.js script present? If yes, a clientnameTracker rather than
pageTracker is necessary.
4. Is the client within ecommerce vertical?
5. Who is going to take-over the installation once the migration is complete?
GA Outcomes
1. Both GA.js AND Universal analytics.js in parallel (most likely outcome)
2. Universal Analytics.js only straight migration.
Remarketing Outcomes
1. Native GA remarketing in Universal (most likely outcome)
2. Adwords remarketing (Only needed for RLSA: AdWords Remarketing Lists for Search Ads)
More tips on GA to Universal migration checklist by Jordan Louis
and a Google checklist are here.
15

STRAIGHT deployment: GA classic to GTM migration
1. Transfer main property UA-00000-1
a. Click the transfer button (you need to be admin user)
b. (optional) Change session timeout setting 30mins & campaign 6months.
c. Wait 48hours until it says "complete" (there is no email notification).
2. Update GA server settings
a. Add ignore referrals GA settings for clientdomain.com
b. Add ignore referrals GA settings for paypal.com and livechat.com etc
c. Add customDimension5 field set to page-level
d. Add contentGroup5 set to tracking code level
e. (optional) If custom search engines such as bt.com, are used, add these in GA settings.

Important: Do NOT replace GA code with GTM until 48hr transfer says "completed"
3. Update Tracking Code
a.
b.
c.

Ensure GA pageview tag for UA-00000-1 within GTM is triggered in Debug mode on DEV.
Find and Replace existing ga.js tracking code in the head with new GTM tracking code in the top
<body>.
Make sure no pages are missing the GTM tag:
i. use report of pageGroup5 and customDimension5 for autoContainerVersion=(not set)
ii. Run a website crawl to search for missing code using ScreamingFrog, WASP or
TagInspector.com or Hub-Scan.com

4. Add ecommerce dataLayer to checkout thankyou page
5. Replace inline code gaq.push with equivalent dataLayer.push code and add GTM
event tags within GTM settings, so there is a seamless migration:
// Example of inline code...
function trackPrompt(e) {
_gaq.push(["_trackEvent", whatPage(), e.data("ga-action"), "Shown"]);
}
source:clientdomain.com/presentation/js/core.combined-e1f32a1.js

6. Add better dataLayer for product pages, and user-interactions.
A youtube video on migration planning is here.

Note1: The "official google upgrade guide" recommends a straight deployment here.
Note2: Custom code that reads the utmz cookie or calls getVisitorCustomVar(1); or backup of
utm.gif images via setLocalGifPath(); is not supported in GA universal, but a workaround exist
here.

16

PARALLEL deployment: GA classic to GTM migration
1. Create empty GTM container and add the code to global header of ALL pages. See
pg9 for details of exact position of the tag.
a. Create GA universal account (UA-00000-3)
i.
ii.
iii.
iv.
v.
2.

Add ignore referrals GA settings for clientdomain.com
Add ignore referrals GA settings for paypal.com and livechat.com etc
Add customDimension5 set to page-level and contentGroup5 set to tracking code level
Optionally, update campaign settings from the 6month default.
If custom search engine lists are used, such as bt.com, then add these in GA settings.

Deploy parallel deployment of Universal (UA-00000-3) via GTM, with GA classic (UA00000-1) running via hardcode.
a. Ensure GA pageview tag for UA-00000-3 is triggered in Debug mode on DEV.
b. Make sure no pages are missing the GTM tag:
i. use report of pageGroup5 and customDimension5 for autoContainerVersion=(not set)
ii. and report of URL and Hostname tables non-matching vlookup for the two GA accounts.

3. Then find & replace GA classic code with event called onload_ga_pageview.
See pg11 for an example, and configure GTM to use this event tag.
a.
b.
c.

Ensure GA pageview tag for UA-00000-1 within GTM is triggered by onload_ga_pageview event.
Within GTM switch UA-00000-3 for UA-00000-1
Run a website crawl to search for missing code using Run a website crawl to search for missing
code using ScreamingFrog, WASP or TagInspector.com or Hub-Scan.com

4. Add ecommerce dataLayer to checkout thankyou page
a.
b.

Check GA classic ecommerce totals vs GA universal ecommerce totals
Click the upgrade to universal button for GA classic UA-00000-1
i. Wait 48hours

5. Replace inline code gaq.push with equivalent dataLayer.push code and add GTM
event tags within GTM settings, so there is a seamless migration:
// Example of inline code...
function trackPrompt(e) {
_gaq.push(["_trackEvent", whatPage(), e.data("ga-action"), "Shown"]);
} // source:clientdomain.com/presentation/js/core.combined-e1f32a1.js

6. Add better dataLayer for product pages, and user-interactions.

A youtube video on migration planning is here.

Note1: a straight migration (without using UA-00000-3 parallel deployment) can also be
done, because once the GA backend data collection is upgraded the collection server
will process both universal and GA classic hits. See next page for an example.
Note2: Custom code that reads the utmz cookie or calls getVisitorCustomVar(1); or
backup of utm.gif images via setLocalGifPath(); is not supported in GA universal,
but a workaround exist here.

17

Universal migrations: ecommerce 3Dsecure non-iframe referrals
If the ecommerce website is using a payment portal (e.g. paypal.com) which uses
3Dsecure & the recommended method of using an <iframe> is not deployed. Then
theses 3Dsecure domains (e.g. verifiedbyvisa.bank.com) will need to be excluded.
If these domains are not added to the exclude referral list; then organic & cpc
transaction sales will be attributed to referrals, and the session will be split in half;
causing pan-session conversion rate issues, an artificial increase in returning visitors
and funnel flow reporting issues.

Fix1: Exclude payment portal referrals TopLevelDomains checklist:
.*(paypal\.com|worldpay\.com|checkout\.google\.com|arcot\.com|mycardsecure\.com|securecode\.com|bnppa
ribas\.com|cardinalcommerce\.com|cm-cic\.com|ecartebleue\.com|edb\.com|evobanco\.com|lloydstsb\.com|modirum\.com|sofort\.com|wlpacs\.com|europsl\.eu|sia\.eu|barclaycard\.co\.uk|barclays\.co\.uk|securesuite\.co\.uk|barclaycard\.de
|berliner-sparkasse\.de|deutsche-bank\.de|lbb\.de|postbank\.de|santander\.de|verifiedbyvisa\.ingdiba\.de|abnamro\.nl|asnbank\.nl|gcsip\.nl|ideal\.ing\.nl|rabobank\.nl|securecode\.ing\.nl|snsbank\.n
l|triodos\.nl|bonuscard\.ch|cardcenter\.ch|postfinance\.ch|swisscard\.ch|viseca\.ch|sermepa\.es|vinea
\.es|luottokunta\.fi|merita\.fi|bpce\.fr|creditmutuel\.fr|monetaonline\.it|cafis-paynet\.jp|dnpcdms\.jp|keb\.co\.kr|3dsecure\.no|swedbank\.se|comdirect\.de|cardnettds\.com|bnz\.co\.nz|gfs\.nb\.se|regiobank\.nl)$

Note: GA universal excluding referral uses a wildcard .*paypal\.com$ not ^paypal\.com$
thus xxxpaypal.com and blog.paypal.com will also be excluded. Read this
Google help page for more info here.

18

Fix2: Assuming that clientdomain.com is present in the exclude referral list. Then GTM
referral override setting patch can be added to the pageview and transaction tags on
the sale complete page only.

The advantage of this solution is that the exclude list does not need to be maintained,
but it does require the separation of the global pageview tag and the sale complete
pageview tag:

Fix3: If the payment portal callback thank you page:
httpS://www.clientdomain.com/checkout/onepage/success/

is not hosted on httpS.

Then the browser would hide document.referrer if the user is redirected from an httpS
payment portal (i.e traffic would defaults to direct without needing a GA exclude referral
patch). However this requires the website to add htaccess redirect rule, hence
managing an exclude referral blacklist will be an easier option.
# Rough example - not tested
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^\/checkout\/onepage\/success$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}$1 [L,R=301]

Tip1: A report on pageGroup2_pageType="confirmed" or landing
page=/checkout/onepage/success which is filtered for returning session only and sorted
descending by entrances or sessions can be used to find exclude referral for the
blacklist.
Tip2: A GA user-defined profile filter can be added to find referrals these domains:
referral: (.+)
medium: ^(referral|referral_self)$
output user-defined: $A1

Tip3: Other exclude referrals to check include...
Livechat TopLevelDomains:
.*(livechat\.com|ladesk\.com)$

Survey TopLevelDomains:
.*(qualaroo\.com|surveymonkey\.com|iperceptions\.com)$

19

Plugins vs custom coding
If you are not using a custom CMS then you can use plugins to generate the dataLayer and
add GTM to all pages, this will save LOTS of time! Here are some examples...

Plugin: GTM for Magento
If you are using Magento, this free plugin will auto enable GTM with the dataLayer values. The
GTM-account ID is set within the configuration.
https://github.com/CVM/Magento_GoogleTagManager
http://www.magentocommerce.com/magento-connect/google-tag-manager-3.html

Note: a separate GTM-xxxx container id can be set within Magento's store view level for
dev.clientdomain.com and www.clientdomain.com see details here. This plugin does not yet
support enhanced ecommerce or onclick one-page-checkout tracking here, and a JSmacro
patch is needed for previousVisitorLifetimeValue calculation here.
Also Fooman has added GTM dataLayer support, but it`s still in beta here & W3C magento
plugin is here.
20

Plugin: GTM for Wordpress & WooCommerce
Wordpress is not designed with a global include setting at the top of the page within the
<body>, but GTM can be either be auto-installed in the footer, or by editing the header.php
template file.
You need to add the GTM-xxxx ID, into Wordpress plugin to activate GTM.

1
1

Supports:
ï‚· comment events
ï‚· remarketing tags
ï‚· native scroll tracking
ï‚· weather tracking
ï‚· enhanced tag security using blacklisting settings
ï‚· works with WooCommerce & ContactForm7
http://wordpress.org/plugins/duracelltomi-google-tag-manager/
(19,714 downloads, Last Updated 1 week ago on 17th Dec 2014)

2
1

http://wordpress.org/plugins/wp-google-tag-manager/stats/
(7,086 downloads, Last Updated 1.9 year ago: 10th January 2013)

3
1
Supports:
ï‚· custom dataLayer via server-side commands.
http://wordpress.org/plugins/metronet-tag-manager/stats/
(1,905 downloads, Last Updated 2 week ago: 11th Dec 2014)
Also worth mention this WooCommerce non-GTM plugin:
http://wordpress.org/plugins/enhanced-e-commerce-for-woocommerce-store/
http://www.tatvic.com/enhanced-ecommerce-google-analytics-plugin-woocommerce/
21

Plugin: GTM for Drupal
I have not tested this, but these are the most popular Drupal plugin:
ï‚· drupal.org/project/google_tag (2,363 installs, last updated 2 weeks ago: 2th Dec 2014)

ï‚·

drupal.org/project/datalayer (100 installs, last updated 2 weeks ago: 2th Dec 2014)
{ "drupalLanguage": "en",
"userUid": "555",
"entityId" : "123",
"entityLabel" : "My Cool Page",
"entityType" : "node",
"entityBundle" : "article",
"entityUid" : "555",
"entityTaxonomy" : {
"my_vocab" : {
"25" : "Term Name",
"26" : "Another Term"
} } }

ï‚·

drupal.org/project/commerce_google_tag_manager (61 installs)

The Drupal has a native JS api that can also be piggybacked:
ï‚· https://www.drupal.org/node/304258#drupal-settings
ï‚· https://plus.google.com/117298997433687198127/posts/Br7cVVkTdUZ

Plugin: GTM for Joomla
Not tested, but only plugin I could find for Joomla:
extensions.joomla.org/extensions/core-enhancements/coding-a-scripts-integration/codesnippets/22448
extensions.joomla.org/search?q=google+tag+manager

22

Planning account structure
For international websites it is important to decide the structure of accounts and
containers, as this will effect access control, maintenance and data collection. Please
be aware of the following GTM restrictions:
ï‚·
ï‚·
ï‚·
ï‚·
ï‚·

GTM has a limit of 200 tags per container
GTM does not officially support two GTM snippets on the same page. This is because
auto-events and gtm.dom become unstable.
Backend data rollup is a GA premium only feature.
The enterprise feature for folderised tags, with access limits per folder does not exist.
Container importing beta is requires whitelisting, it is not enabled by default.

One account per organisation (1 organisation)
1
1

Account
(ClientName)

Container1

Container2

(LIVE domain)

(DEV domain)

Main Site
Tags

Blog Tags

Shop Tags

One account per Brand (2 brands in this example)
2
1
Account

(Brand1)

(Brand2)

Container1

Container2

(LIVE domain)

(DEV domain)

Main Site
Tags

3
1

Account

Blog Tags

Shop Tags

One account per Brand per country (196 countries)

UK

US

(Country2)

(Country1)

Container1
(clientdomain.co.uk)

Main Site Tags

Blog Tags

Shop Tags

23

Position of the dataLayer and gtm.js
Some CMS`s are not built with a global top <body> include (only a global header or
footer include) or there is a need to do a like-for-like replacement of GA in the header
for GTM in the header. Thus, here are some possible alternatives:
11.
2.
2
1
13.
3
1

DataLayer in <head> and GTM in top <body> (2 include files)
Both DataLayer & GTM in top <body> (1 include file)
Both DataLayer & GTM JavaScript in <head>, with GTM iframe in footer (2
include files)

Existing GA setup:

Existing

GTM setup options:

1
1

3
1

2
1

Notes:
ï‚·
ï‚·

Google Webmaster Tools verification only works in option1.
For option3: If customHTML is used, then a blocking-rule/patch for IE7 must be added
for example: navigator.userAgent JavaScript variable which matches RegEx ^.+
\(.*MSIE [6-7]\.0; .*\).*$

ï‚·

For option3: GTM team does not test GTM in <head> thus there is no guarantee that it
will continue to work the future.

24

Planning the setup of development environment
When setting up a DEV and LIVE environment there are 3 solutions, depending on the
complexity of your installation, flexibility of your server and your attitude towards risk.
Note: At the time of writing, GTM does not support an external API for source control,
thus configurations need to be manually copied. However, tags can be copied and
iMacro browser automation can be used instead.
1
1

Two separate containers (GTM-dev and GTM-dev) insert via php server-side switch
(safest option):
<?php
switch ($_SERVER['HTTP_HOST']) {
case 'localhost':
case 'dev.clientdomain.com':
case 'staging.clientdomain.com':
$gtm_account_id = 'GTM-DEV'; // Dev GTM
break;
case 'www.clientdomain.com':
$gtm_account_id = 'GTM-LIVE'; // LIVE GTM
break;
default:
$gtm_account_id = 'GTM-LIVE'; // default to LIVE
}
?>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-<?php echo
$gtm_account_id ?>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-<?php echo $gtm_account_id ?>');</script>
<!-- End Google Tag Manager -->

2
1

One container with prepended identifier of "dev | live"
(less dangerous option, but double number of tags).
dev_<TagType>_<TagName>_<TagID>
e.g. dev_GA_classic_pageview_UA-00000-2
live_<TagType>_<TagName>_<TagID>
e.g. live_GA_classic_pageview_UA-00000-1

3
1

One container using preview & debug extensively!
(most dangerous option, as it requires write access to live)

Related post on this discussion is here.

25

GTM-xxxx account ID for DEV and LIVE
1
If you are using configuration
then two containers will need to be created for
each environment, each with a different
GTM-xxxx.
1
For example:

The GTM with a live account (GTM-LIVE), staging account (GTM-DEV) will need to be
set using server-side settings, because javascript does not load within <noscript>
tags.
<body>
<!-- Google Tag Manager container for GA -->
<noscript>
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-xxxx>
</iframe>
</noscript>
<script>
window,document,'script','dataLayer','GTM-xxxx');
</script>

Note: the GA UA-xxxx-x ID is set within GTM (using a macro default), there is no need
for a cascading hostname lookup.

26

2
3
1
1
If you are not using a server-side switch, and thus are using option 2 or 3 from the
previous page. Then you will need to add a cascading lookup table macro to
selectively output the correct accountID UA-00000-2 or UA-00000-1.

Cascading lookup tables for UA-xxxx-x

1. Hostname

dev.clientdomain.com
(UA-00000-2)

2. DebugMode
True match
(UA-00000-2)

4. Default
(UA-00000-1)

27

Deciding on a thank you page trigger method
This step is not needed; if a Magento or Wordpress plugin are used, which generate a
reliable dataLayer on the confirmation and cart pages.
There are 5 possible ways to triggering a thankyou page:
1. {{dataLayer.google_tag_params.ecomm_pagetype}} = purchase
2. {{dataLayer.ecommerce.purchase.actionField.id}} not like ^(undefined)?$
3. {{dataLayer.event}}=transaction
4. {{js_document.title}}=Thankyou for Ordering
5. {{url path}}=/thankyou.html

IMPORTANT: Option4{{url path}} is case sensitive in rules & lookup tables. Thus
applying lowercase patch and remove trailing "/" via a jsmacro is recommended to
increase triggering accuracy. Also {{url path}} triggers will break if the page is
renamed to /new-thankyou-2.html
DataLayer based{{pagetype}} & {{Event}} methods will continue to work if the URL
is changed . They do not require maintenance and are a better long term solution.
<!-- Examples of a dataLayer for confirmation pages -->
<script>
// Adwords remarketing dataLayer
dataLayer = [{"google_tag_params": {"ecomm_pagetype": "purchase"} }];
// GTM dataLayer
dataLayer = [{"page.category.pageType": "confirmation","event":
"transaction"}];
// W3C digitalData layer v1.0
window.digitalData.page = {"category": {"pageType": "confirmation"}};
// Qubit universal_variable dataLayer v1.2.1
window.universal_variable.page = {"type": "confirmation"};
</script>

IMPORTANT: When deploying GTM on multiple CMS, when the dataLayer is added in
stages a hybrid approach is necessary, to ensure that sale confirmation rule always
triggers. This uses a cascading URL lookup table, here is an example:
1. DataLayer Value
{{ecomm_pagetype}}
=purchase

2. DataLayer Event
{{event}}=
transaction

3. URL matched
{{url path}}=
/checkout/success

28

4.Unmatched
Default Value:
Not a conversion

Deciding on a rule trigger position (onload, onready or page footer)
All GTM rules have an implicit event equals gtm.js. However, in some circumstances it
is necessary to override this default behaviour.
Function
Pageview (gtm.js) default
DOM Ready (gtm.dom)
Page Load (gtm.load)
Timer (gtm.timer auto-event)

Initialisation
start loading
ready
footer
2secs delay

Delay
-0
-0.5% pageviews
-2% pageviews
-2% pageviews

Note: dataLayer = [{"event": "header_datalayer_loaded"}]; will trigger at the
same time as event equals gtm.js
Suggested tag triggering positions
Function
Example Tags
Pageview
GA pageview tag
(gtm.js) default Async Adwords conversion tags
Native Ecommerce tag using dataLayer

Delay
-0

DOM Ready
(gtm.dom)

Re-mapped Ecommerce script
-0.5% pageviews
Synchronous Conversion script (e.g. Bing)
Facebook/Twitter API script
YahooWeather IP-to-weather API script
DemandBase IP-to-businessType API script
ScrollTracking script
linkClickListener - gtm.linkClick
formSubmitListener - gtm.formSubmit
historyListner - gtm.historyChange

Page Load
(gtm.load)

Adwords Remarketing tags
Survey popup script
ClickTale

-2% pageviews

GTM does not currently support synchronous loading of Adsense or A/B testing tags or
native tag dependencies, but it does support GA tag hitCallback, gtm.timer=1,2,3 per
tag and a work-arround for daisy-chaining a sequency of events.

29

Seamless migration of Tags to GTM
When moving hardcoded tags into GTM, the hard code can be replaced with an event
named <tagPostion>_<vendorName>_<trackerType> for example:
<!-- GA PAGEVIEW tracker WAS here moved into GoogleTagManager -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({"event": "onload_ga_pageview"});
</script>

Then a rule needs to be added into GTM to trigger this tag above.
The advantage of this method is that it means that when the old code is replaced with
GTM it works seamlessly, and developers just need to find and replace :)
IMPORTANT: if both the legacy GA code and an onload {{Event}} trigger are active on
a page, then the pageview will trigger TWICE! This is because GTM logic uses an
either-or rule. Hence, remember to replace the GA code with
dataLayer.push({"event": "onload_ga_pageview"});

Note: It is possible to add a pageview blocking rule to prevent double firing, if the GA
classic {{_gaq}} variable is defined, but this is not a 100% reliable solution; as some
3rd party plugins will declare _gaq. See this post for details.
The same method applies to DoubleClick code, except page specific values can also
be passed in:
<!-- DoubleClick COUNTER was here - moved into GoogleTagManager
Creation Date: 01/01/2014 -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
"event": "onload_doubleclick_counter",
"src": "3018669",
"type": "atter993",
"cat": "ithom544",
"ord": "1"
});
</script>

30

Deciding on a dataLayer schema
There is massive non-standardisation in the TMS industry regarding JSON object
names, which is:
ï‚· harming automation and increasing implementation time
ï‚· complicating the process of migrating between TMS vendors
ï‚· fragmenting data collection validators (e.g. Qubit validator or W3C validator)
Additionally, dynamic remarketing of individual products to customers for display ads
within ecommerce and travel verticals is driving industry standardisation. Thus
consolidation of JSON object names is inevitable.
However, there is no clear winner in this race for standardisation.
At the time of writing, it does not matter which naming schema you select, so long as
you pick one and stick to this! Changing a schema mid-way through a project will
cause significant delays within the QA process.
Here are the 5 most common schema`s (sorted in order of preference):
1.
2.
3.
4.
5.

Automatic CMS native dataLayer names (Magento2, Shopify, piggybacking of CQ5)
Automatic CMS plugin dataLayer names (e.g Wordpress, Magento1, Drupal)
Automatic CMS plugin for other TMS (e.g. DemandWare piggybacking of Qubit/Telium)
Manual GTMs dataLayer names (fixed for ecommerce & social). See page 7.
Manual W3C digitalData names. See W3C cheatsheet on page 6.

DataLayers are monogamous, once a global JavaScipt objects is output to the page, it
is easy to re-map this to the relevant fields in GTM, via a customHTML mapping script.
For example it is easy to re-map GTMs dataLayer >> W3C digitalData or vice-versa.
However, there is a ~0.5% loss in recorded transaction when using these mapping
scripts because a small delay is added using gtm.dom (rather than gtm.js started) and
the customHTML/JSmacro mapping script add an extra level of complexity (especially
for enhanced ecommerce, or when using arrays for multiple item within a basket).
Thus, where possible, a native dataLayer should be used; which does not require the
need to wait for gtm.dom ready and because this is added automatically - it is reduces
the risk that a developer will incorrectly render JSON values, thus reducing QA time.
Magento2 and Shopify are the only CMS that will soon natively outputting a standard
dataLayer by default; removing the need to select a schema!
If you are not on one of these CMS`s, or are unable to piggyback an existing
dataLayer, then you will need to use a manual dataLayer, and thus you will need to go
through the process of decide on a naming convention standard. Please read the next
page to start this process....

31

Deciding on a dataLayer naming convention standard
The dataLayer is a critical part of GTM. Hence it is important that a standardised
structure for naming of JSON objects and values is "set in concrete" at an early stage,
as this will save significant time in QA testing. Also, JavaScript matching is case
sensitive, thus using the wrong case will mean that no match is found, causing data
discrepancies.
a) Capitalistation of variableNames
1. camelCase e.g. "variableNameId" (GTM standard) [recommended]
2. camelCase e.g. "variableNameID" (W3C standard)
3. lowercase e.g. "variablenameid" (Qubit & Adwords remarketing standard)

b) Capitalistation of values
1. lowercase e.g. "product name" or "/search?q=keyword" [recommended]
2. camelCase e.g. "Product Name" or "/search?q=Keyword"

Note: capitalisation of value can be patched within GA using lowercase filters, but
fixing the client-side code is recommended.
c) Encapsulation of text values
1. double quotation marks e.g. "value" (W3C and RFC4627 standard) [recommended]
2. single quotation marks e.g. 'value' (GTM standard)

Note1: it is not necessary to escape single quotes in productNames or
categoryNames if these are encapsulated in double-quotes. For example
"transactionProducts":[{ "name": "11' heals", "category": "Big Shoe's" }],
Note2: for inline encapsulation single quotes should be used. For example:
<a href= "#" onclick="dataLayer.push({'event': 'value'});">
Note3: it is recommended to encapsulation integers "1000" to remove risk of
comma breaking ecommerce code: 1,000
e) Encapsulation of variableNames
1. quotation marks e.g. 'variableName' or "variableName"
(GTM standard) [recommended]
2. no encapsulation e.g. variableName,
with exception of JS reserve words (W3C standard)

f) Separator for text values
1.
2.
3.
4.

Dash
Underscore
Whitespace
Plus

e.g. "header-datalayer-loaded"
e.g. "header_datalayer_loaded"
e.g. "blue shoes" (GTM ecommerce) [recommended]
e.g. "blue+shoes" (Gets converted to whitespace by GA)

g) Nesting
1. no nesting e.g. transationId (transactionProducts.id exception) (GTM legacy)
2. dots nesting e.g. ecommerce.purchase.actionField.id(GTM enhanced & W3C standard)
3. underscore e.g. ecomm_pagetype, ecomm_prodid (Adwords Remarketing standard)

h) Language for international websites
It is recommended to default English with the foreign name added as a comment. For
example:
1. "variableNameId": "value"; // Translation: Nom de la objet Id [recommended]
2. "nomDeLaObjetId": "value"; // Traduction: variableNameId
Tip: If a deployment has rolled-out with {{pageVirtual}}{{page_virtual}}{{pagevirtual}} it is possible to use
simple patch within GTM to cobine these typos.

32

Clean page mark-up and avoidance of use of inline code
Inorder to make the installation robust & easy to maintain, avoid running inline GA
code. Instead, use GTM auto-events or jQuery customHTML, to append onclick events
on-the-fly to page elements.
This requires that DOM elements must be named in a consistent way, because the
tracking will be dependent on these names. If IDs, Classes or DOM elements are
renamed, then tracking functionality will be break!
ID attributes on div elements:
<a href="#" id="tracking-link1">click here</a>

CLASS attributes:
<div class="tracking-navigation-links">
<a href="#" id="tracking-link1">click here</a>
</div>

HTML5 data attributes:
<a href="#" data-tracking-action="click"
data-tracking-event="video"
data-tracking-entity="component"
data-tracking-event-context-id="12345"
data-tracking-event-context-category="video"
data-tracking-event-context-action="play"
data-tracking-event-context-label="video name"
data-tracking-event-context-value="0"
data-tracking-event-context-noninteractive="false">click here</a>

Phone number markup:
<span id="telephoneNumber1" class="tracking-number-replace tel
number" itemprop="telephone">
<a href="tel:+44123400000">+44 (0)1234 00000</a></span>

Form markup for sensitive fields:
<input id="CreditCardPin" type="text" class="tracking-sensitive
ClickTaleSensitive no-mouseflow sessioncamexclude -metrika-nokeys">

YouTube & Vimeo require enablejsapi=1 or api=1:
<iframe src="//www.youtube.com/embed/fBLc6UedJ98?enablejsapi=1" id="ytplayer"
width="640" height="510" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
<iframe src="http://player.vimeo.com/video/76167614?api=1" id="vimeo_player_1"
width="640" height="510" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe><!-- Note: vimeo does not support SSL -->

Page Title:
<title>Error 404 - Page not found</title>
<title>Thankyou for Ordering</title>
<title>Thankyou for Contacting</title>

IMPORTANT: If data variables are output by the CMS, or by another TMS, then they
can be re-mapped to GTM. There is no need to declare these variables twice! For
example:
window.isLoggedIn = "true";

or
window.universal_variable.events.push({"action": "product-added-tobasket"});

There is a great blog post about clean element markup
by Jeff Chasin here.
You can test for semantic and structured markup using these tools:
ï‚·
ï‚·

services.w3.org/xslt?xmlfile=http://services.w3.org/tidy/tidy?docAddr=http://www.CLIENTDOMAIN.COM/&p
assThroughXHTML=1&xslfile=http://www.w3.org/2002/08/extract-semantic.xsl
www.google.com/webmasters/markup-tester/corporatecontacts

33

jQuery vs GTM auto-events
As part of the planning phase, it is necessary to determine which framework is going to
be used for listening for DOM changes. You need to pick one - not both.

Advantages
ï‚·
ï‚·
ï‚·
ï‚·

TMS agnostic - can be migrated from GTM to Qubit or via-versa.
Existing jQuery events can be piggybacked
If large website or complex markup then jQuery can handle the logic in one
customHTML tag rather than several.
Lots of native functions, easier to traverse selectors and lots of 3rd party customisations.

Disadvantages
ï‚·
ï‚·

Requires Developer resources
Requires consistent version of jQuery site-wide:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
or <script src="//code.jquery.com/jquery-latest.min.js"></script>

ï‚·

If not possible to load via CDN (e.g banking website) then this will cause latency issues
as there is a large initial download.

Advantages
ï‚·
ï‚·
ï‚·
ï‚·
ï‚·

Standardised version deployed sitewide
Easier for non-developers to enabled
Will soon support better UI for selecting button classes etc
Built in JS error tracking
If a tag importing is introduced - then it will be easier to enable functions.

Disadvantages
ï‚·
ï‚·
ï‚·

ï‚·

Can be stomped-on by jQuery or other JS append events
Creates a dependency on native GTM function, making it harder to change from GTM.
Only support 6 functions
o gtm.pageError
o gtm.formSubmit
o gtm.click
o gtm.linkClick
o gtm.historyChange
o gtm.timer
Additional functions such as gtm.change selectors for menu links can be added via
customHTML triggered via "event": "header_datalayer_loaded".

Note: Both methods require reliable markup of unique IDs, classes and data-attributes
34

Logins & permissions
You will need to create a GTM account and container here:
www.google.com/tagmanager/
username: gtm.ClientDomain.com@gmail.com
password: choose-your-password
Role

Job title

Manage
user
permissions

View
container

Edit
container

Publish
or delete
container

Administrator

Systems
Admin

Yes

Yes

*

*

Tester

Marketer

Yes

Contributor

Technical
Analyst

Yes

Yes

Publisher

Developer

Yes

Yes

*


✎
Yes

✎☠

*Warning: Administrators have the ability to escalate their own permissions!
AnalyticsAgency recommend that all GTM account with delete ☠, publish-access  or
manage-user-permissions have 2-stage authentication via sms or iphone app to
enhance security.
youtube.com/watch?v=zMabEyrtPRg and
support.google.com/accounts/bin/answer.py?answer=180744

Related post here...

35

Debug process
How to avoid getting burned by tags here.

How to debug video
We recommend your developers watch this short video on how GTM works:
https://www.youtube.com/watch?v=KRvbFpeZ11Y&list=PLFwbZmNsefUvq930NjgBoQeTUX6foIhP&index=2

36

Chrome Tag Assist Plugin - MUST be installed
It is a requirement that developers install the chrome plugin to validate the GTM code:
https://chrome.google.com/webstore/detail/tag-assistant-bygoogle/kejbdjndbnbjgmefkgdddjlbokphdefk?hl=en
https://www.youtube.com/watch?v=4AqanTBA9X4

It is recommended to set chrome plugin to "Detailed" mode, rather than "Basic" mode:

37

Here is an example of the Chrome validator in action:

Clicking on the "not working" shows details:

Tip: JSON validator is really good for checking the dataLayer
http://jsonlint.com/ for example
{
"variableName": "textValue",
"variableName": "textValue"
}

Note: jsonlint.com does not like HTML comments, and single-quotes need to be
changed to double-quotes in order to validate.
Also JSON formatter for chrome can also be used to make JSON easier to read.

38

GTM scripts examples
ClientDomain will insert the appropriate GTM container script tag at the top of the
page directly after the opening <body> tag and not within any nested <div> an example
is shown on the next page.
The GTM-accountID`s are:
ï‚·
ï‚·

DEV GTM account is GTM-DEV (dev.ClientDomain.com)
LIVE GTM account is GTM- LIVE (www.ClientDomain.com)

For sale complete and login pages a dataLayer for transaction variables and custom
dimensions will need to be populated.

GTM configuration - dont use inline configuration
In general auto-event modules and customHTML modules for Youtube, Facebook,
Twitter and ScrollTracking modules should be enabled via GTM constant string macros
and conditional rules - it should not set within the page.
// GTM settings: onpage auto-event overrides
"settings_gtm_isAutoEvent_pageErrorTrackingEnabled" : "true", // gtm.pageError for JS error tracking
"settings_gtm_isAutoEvent_historyChangeTrackingEnabled": "true", // gtm.historyChange for AJAX tracking
"settings_gtm_isAutoEvent_linkClickTrackingEnabled" : "true", // gtm.linkClick for OutboundLink Tracking
"settings_gtm_isAutoEvent_clickTrackingEnabled"
: "false", // gtm.click
"settings_gtm_isAutoEvent_timerTrackingEnabled"
: "false", // gtm.timer for heartbeats
"settings_gtm_isAutoEvent_formSubmitTrackingEnabled": "false", // gtm.formSubmit - default 2sec delay
// GTM settings: onpage customHTML overrides
"settings_gtm_isScrollTrackingEnabled"
: "false", // Blog content pages customHTML script
"settings_gtm_isYoutubeTrackingEnabled" : "false", // Youtube API auto-tracking customHTML script
"settings_gtm_isFacebookAndTwitterButtonTrackingEnabled": "false", //Auto-social button tracking
// GEO-ip mapping and Browsers DNT response
"session_geoIpStatus"
"session_geoIpCountryCode"
"session_geoIpContinentCode"
"session_geoIpIsCookieConsentRequired"
"session_preferenceForDnt"

:
:
:
:
:

geoplugin_status, // 403 error, 200 is lookup ok
geoplugin_countryCode, // geoplugin JS variable
geoplugin_continentCode, // geoplugin JS variable
geop1ugin_cookieConsent, // JS variable
window.navigator.doNotTrack,// 1|0|"not-set" JS dom function

Similarly, these settings should be configured within GTM constant string macros and
lookup tables - it should not set within the page.
// GA settings: onpage customHTML settings
"settings_ga_id": "UA-00000-1", // UA-00000-2 DEV, UA-00000-1 on LIVE
"settings_ga_setDomainName": "clientdomain.com", // "auto" or "none" or "clientdomain.com"
"settings_gtm_debugMode": false, // true or false
// Adwords settings
"google_conversion_id"
: "123456",
"google_conversion_label"
: "other" // Enter Adwords label
//, "google_conversion_value" : "250.00", // same value as dataLayer.ecommerce.purchase.actionField.revenue
// GA settings: onpage customHTML settings
"settings_ga_externalCrossDomainlinksToDecorate": "otherdomain1.com, mycart.com", // Separate using comma
"settings_ga_listDownloadLinkTrackingFiles": "pdf|doc|docx|xls|xlsx", // Separate using | pipes
"settings_ga_isInPageLinkTrackingEnabled": "true", // Improves accuracy of internal Link tracking
"settings_ga_isHashUrlFragmentsTrackingEnabled": "false", //Append location.hash pageVirtual#url

The only exception to this the gtm.blacklist failsafe switch, that needs to be inline:
// "gtm.blacklist": ["customScripts"], // Uncomment to disable custom JS for debugging purposes

39

<!-- Existing dataLayer - used to turn ServerSide variables into JS -->
<script>
// window.isLoggedIn = "true";
</script>
<!-- GeoIP to country dataLayer variables - WARNING non-ssl script -->
<script src="http://www.geoplugin.net/javascript.gp?ver=3.5.1" type="text/javascript"></script>
<script src="http://www.geoplugin.net/extras/cookielaw.js" type="text/javascript"></script>
<script>window.dataLayer = window.dataLayer || [];
dataLayer.push({'event': 'header_geoplugin_loaded'});
</script>
<!-- jQuery 1.11.1 loaded via Google CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>window.jQuery || document.write("<script src='\/\/ClientDomain.com\/js\/common\/jquery\/jquery1.11.1.min.js'><\/script>");</script><script>jQuery.noConflict();</script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script>window.dataLayer = window.dataLayer || [];
dataLayer.push({'event': 'header_jquery_loaded'});
</script>
<!-- Google Tag Manager dataLayer for global header -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
// Global settings
"version"
: "1.0", // W3C digital dataLayer version
"environmentIdentifier"
: "dev", // dev, staging or live
"pageBrandName"
: "big brand", // If using multiple brands in rollup then use this field
"pageLanguage"
: "en", // locale-code for page language e.g. en
"pageCountry"
: "us", // Use 2character ISO Country list e.g. us
"pageGeoRegion"
: "new york", // Only needed for large localised websites
// Page values
"pageVirtual"
: "", // e.g. "/virtual" + location.pathname + location.search
"pageAttributesSysEnv"
: "desktop", // Responsive CSS = desktop | tablet | mobile.
"pageHttpResponseCode"
: "<?php http_response_code(); ?>", // e.g 200 or 404 or 500
"page.id"
: "1234",
"pageSiteSearchResults"
: "", // 0 means 0 results returned
//"pageGroup1_manualClassification": "", // reserved slot for manual names
"pageGroup2_category"
: "", // pageCategory
"pageGroup3_subCategory"
: "", // pageSubcategory, pagePostType or paymentStep
"pageGroup4_templateName"
: "", // pageTemplateName, pageBreadcrumb or pagePostAuthor
//"pageGroup5_containerVersion": "", // reserved slot for {{autoContainerVersion}}
"pageContentCreated"
: "", // 2013-01-01 server-side variable
"pageContentModified"
: "", // 2013-01-01 server-side variable
"pageForumPosts"
: "", // e.g. 25
// Note: these are the dataLayer names output by Duracell Tomi WordPress plugin:
pageCategory,pagePostType,pagePostType2,pagePostAuthor,visitorLoginState,visitorType,inputClass,input
Name
// Visitors preference and Safari view mode
"user_authIsUserIdToSessionIdOverrideEnabled": "false", // true|false is set on Login or Register complete
page. userIDoveride MUST default to false. Only change if consent gained or DNT=0
"session_xPreview": "<?php if ($_SERVER['HTTP_X_PURPOSE'] == 'preview' {'preview'} else {''} ?>", // Safari
loading page in preview mode
// Ecommerce payment page variables
"ecommerce": {
"currencyCode"
: "", // LOCAL currency profile
"purchase": { // promo_click > detail > add | remove > checkout | checkout_option >>> purchase | refund
"actionField": {
"step"
: "", // 1-6
"option"
: "", // checkout > login > delivery > billing > payments > complete
"id"
: "",
"affiliation"
: "", // optional
"revenue"
: "", // 120*1quantity + 120*1quantity + 10shipping
"tax"
: "", // 250 * (1-(100%/120%))
"shipping"
: "", // Includes Tax: 8.33 + tax = 10.00
"shippingMethod"
: "", // optional
"date"
: "", // optional
"coupon"
: "", // optional - aka transactionPromoCode or transactionVoucher
"couponDiscount"
: "", // optional - how much reduced by, not percentage
"paymentType"
: "", // optional - can also be used for CreditCard, Paypal, etc
"type"
: "", // optional
"subTotalIncludeTax"
: "" // Indicates whether TransactionTotal includes tax
},
"products": [
{"id":"", "name":"", "category":"", "brand":"", "variant":"", "coupon":"", "price":"", "quantity":""},
{"id":"", "name":"", "category":"", "brand":"", "variant":"", "coupon":"", "price":"", "quantity":""}
]
}
},
// CustomDimensions persistence can be userScope=6months, sessionScope=30mins or hitScope=pageScope
"user.id"
: "", // cd001: userScope -auth.user.getId
"cart.id"
: "", // cd014: sessionScope
//, "containerVersion"
: "", // cd005: reserved slot for userScope {{containerVersion}}
// CustomMetrics type can be integerType, currencyType (decimals), timeType
"cart.total"
: "", // cm002: currencyType - ecomm_totalvalue
"visitorLifetimeValue": "", // cm001: currencyType - Includes Tax: ($100*2+$10)+tax = $250.00
"firstPurchaseDate": new Date("January 01 2014 23:59:59"), // cd007: userScope customer lifetime

40

// Adwords Dynamic Remarketing dimensions for product image IDs
// support.google.com/adwords/answer/2476691?hl=en & support.google.com/adwords/answer/3103357?hl=en
// & support.google.com/tagmanager/answer/3002580?hl=en
"google_tag_params": {
"ecomm_pagetype": "purchase",//cd015:home|category|product|cart|purchase|other {{page.category.pageType}}
"ecomm_paymentstep": dataLayer.ecommerce.purchase.actionField.option,//cd016:
cart|login|delivery|billing|payments|complete
"ecomm_prodid"
: [""], // cd017: e.g. ["sku_111","sku_222"] {{ecommerce.products[n].id}}
"ecomm_totalvalue"
: dataLayer.ecommerce.purchase.actionField.revenue, // cm002: £100
"ecomm_pname"
: [""], // cd018: optional {{ecommerce.products[n].name}}
"ecomm_pcat"
: [""], // cd019: optional {{ecommerce.products[n].category}}
"ecomm_rec_prodid"
: [""], // cd020: e.g. shoe shine {{ecommerce.recommendation[n].id}}
// Auth logged-in variables
//"user.id"
: "", // cd001:WARNING never use userId, cartId or sessionId for remarketing
"user_isRegistered"
: "", // cd002: y|n users has an account?
"user_isLoggedIn"
: "", // cd003: y|n users is signed-in?
"user_isReturnCustomer"
: "", // cd004: y|n users has transacted already?
"user_memberType"
: "", // cd006: Free Member, Premium Member or Enterprise Member
"user_memberTypeClass"
: "", // cd007: sub-types of memberClass
"user_ageRange"
: "", // cd008: Age range
"user_gender"
: "", // cd009: Gender
"user_customerQualityScore"
: "", // cd010: Customer Quality Score - High, Med, Low
"user_highSpenderScore"
: "", // cd011: High Spender Score - High, Med, Low
"user_loyaltyScore"
: "", // cd012: Loyalty Score - High, Med, Low
"session_testVariant"
: "" // cd013: combine A/B testing offer with remarketing
//, "session_type"
: "", // cd000: new|returning 30min session native GA field UserType },
},
"event": "header_datalayer_loaded" // Used to trigger dataLayer dependencies
//, "event"
: "transaction" // Trigger transaction submission to GA via GTM
});
// interoperability with legacy Adwords google_tag_params
window.google_tag_params = window.google_tag_params || [];
google_tag_params.push({"google_tag_params": window.dataLayer});
</script>
<!-- End Google Tag Manager Data Layer -->
</HEAD>
<BODY>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-xxxx" height="0" width="0"
style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-xxxx');
</script>
<!-- VERSION: GTM_October_v1 -->
<!-- WEBSITE: clientdomain.com -->
<!-- CATEGORY: ecommerce -->
<!-- MARKET: UK -->
<!-- GTM-LIVE:UA-00000-1 | GTM-DEV:UA-00000-2 :: rolledupTracker
-->
<!-- GTM-LIVE:UA-111111-1 | GTM-DEV:UA-111111-2 :: localCountryTracker -->
<!-- Replace GTM-xxxx with GTM-LIVE for live, or GTM-DEV for dev -->
<!-- End Google Tag Manager -->

41

Adwords dynamic remarketing custom categories
Remarket to non-converted ex-visitors with an ad showing a picture of the product
they just viewed, this is enabled via the Google Display Network.

<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
"google_tag_params": {
// Retail - Google Merchant Center feed required for retail
"ecomm_prodid": "12345", // product viewed - ecommerce.products[n].id
"ecomm_pagetype": "home | category | searchresults | product | cart | purchase | other",
"ecomm_totalvalue": "49.99", // Product price - dataLayer.ecommerce.purchase.actionField.revenue
"ecomm_pname": [""], // ecommerce.products[n].name
"ecomm_pcat": [""], // ecommerce.products[n].category
"ecomm_rec_prodid": [""], // ecommerce.recommendation[n].id
"ecomm_paymentstep":"cart | login | delivery | billing | payments | complete",//purchase.actionField.option
// Flights
"flight_destid": "PAR", // flight viewed
"flight_originid": "LON", // flight viewed
"flight_pagetype": "home | searchresults | offerdetail | cart | purchase",
"flight_startdate": "2015-01-01", // startDate of flight. YYYY-MM-DD format
"flight_enddate": "2015-01-08", // endDate of flight. YYYY-MM-DD format
"flight_totalvalue": "100", // Flight price
// Travel
"travel_destid": "PAR", // travel option viewed
"travel_originid": "LON", // travel option viewed
"travel_pagetype": "home | searchresults | offerdetail | conversionintent | conversion | other",
"travel_startdate": "2015-01-01", // startDate of trip. YYYY-MM-DD format
"travel_enddate": "2015-01-08", // endDate of trip. YYYY-MM-DD format
"travel_totalvalue": "100", // Trip price
// Hotels and rentals
"hrental_id": "52639", // hotel or rental viewed
"hrental_pagetype": "home | searchresults | offerdetail | conversionintent | conversion | other",
"hrental_startdate": "2015-01-01", // startDate of rental. YYYY-MM-DD format
"hrental_enddate": "2015-01-01", // endDate of rental. YYYY-MM-DD format
"hrental_totalvalue": "100", // Price of hotel or rental.
// Real estate
"listing_id": "mtv_12345", // listing viewed
"listing_pagetype": "home | searchresults | offerdetail | conversionintent | conversion | other",
"listing_totalvalue": "600000", // Listing price
// Jobs
"job_id": "1255", // job viewed
"job_locid": "Mountain View", // Location job viewed
"job_pagetype": "home | searchresults | offerdetail | conversionintent | conversion | other",
"job_totalvalue": "100000", // Salary of the Job
// Local deals
"local_id": "1234", // local deal viewed
"local_pagetype": "home | searchresults | offerdetail | conversionintent | conversion",
"local_totalvalue": "100", // Price of local deal
// Custom
"dynx_itemid": "Sedan", // item viewed
"dynx_itemid2": "Red", // item viewed
"dynx_pagetype": "home | searchresults | offerdetail | conversionintent | conversion | other",
"dynx_totalvalue": "20000" // Item price
}
});</script>

42

Ecommerce Transactions on sale complete pages
AnalyticsAgency will set GTM to trigger on one of these three rules:
1. {{dataLayer.google_tag_params.
ecomm_pagetype}}=purchase
2. {{Event}}=transaction
3. {{url path}}=/checkout/onepage/success

Do not remove the existing GA ecommerce code yet:
<script type="text/javascript">
// Existing GA ecommerce code on /checkout/thankyou.htm
var _gaq = _gaq || [];
_gaq.push(['_setDomainName','clientdomain.com'],['_setAccount','UA-00000-2']);
_gaq.push(['_addTrans',
'T000012345',
// Order_ID
'Aff123',
// Affiliation
'130.00',
// Revenue - Inc VAT and Shipping
'20.00',
// Vat Tax @ 20%
'10.00',
// Shipping - Inc VAT
'','',''
// Depreciated Region, City & Country
]);
_gaq.push(['_addItem',
'T000012345',
// Order_ID
'BS123',
// ProductSKU or ProductID - required
'Blue Shoes',
// ProductName - Pls \escaped quotes & commas
'Shoes',
// prod_category - Pls \escaped quotes & commas
'120.00',
// Price Inc VAT @ 20%
'1'
]);
_gaq.push(['_trackTrans']); // submit transaction
</script>

On the sale complete pages /checkout/onepage/success insert the following dataLayer
making sure that the variables displayed in <bold> are changed appropriately.
<!-- Google Tag Manager dataLayer for Sale page only -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
// Global settings
"version"
: "1.0", // W3C digital dataLayer version
"environmentIdentifier"
: "dev", // dev, staging or live
"pageBrandName"
: "big brand", // If using multiple brands in rollup then use this field
"pageLanguage"
: "en", // locale-code for page language e.g. en
"pageCountry"
: "us", // Use 2character ISO Country list e.g. us
"pageGeoRegion"
: "new york", // Only needed for large localised websites
// Page values
"pageVirtual"
: "", // e.g. "/virtual" + location.pathname + location.search
"pageAttributesSysEnv"
: "desktop", // Responsive CSS = desktop | tablet | mobile.
"pageHttpResponseCode"
: "<?php http_response_code(); ?>", // e.g 200 or 404 or 500
"page.id"
: "1234",
"pageSiteSearchResults"
: "", // 0 means 0 results returned
//"pageGroup1_manualClassification": "", // reserved slot for manual names
"pageGroup2_category"
: "", // pageCategory
"pageGroup3_subCategory"
: "", // pageSubcategory, pagePostType or paymentStep
"pageGroup4_templateName"
: "", // pageTemplateName, pageBreadcrumb or pagePostAuthor
//"pageGroup5_containerVersion" : "", // reserved slot for {{autoContainerVersion}}
"pageContentCreated"
: "", // 2013-01-01 server-side variable
"pageContentModified"
: "", // 2013-01-01 server-side variable
"pageForumPosts"
: "", // e.g. 25
// Visitors preference and Safari view mode
"user_authIsUserIdToSessionIdOverrideEnabled": "false", // true|false is set on Login or Register complete
page. userIDoveride MUST default to false. Only change if consent gained or DNT=0
"session_xPreview": "<?php if ($_SERVER['HTTP_X_PURPOSE'] == 'preview' {'preview'} else {''} ?>", // Safari
loading page in preview mode

43

// Ecommerce payment page variables
"ecommerce": {
"currencyCode"
: "USD", // LOCAL currency profile
"purchase": { // promo_click > detail > add | remove > checkout | checkout_option >>> purchase | refund
"actionField": {
"step"
: "6", // 1-6
"option"
: "complete", // checkout > login > delivery > billing > payments > complete
"id"
: "T000012345",
"affiliation"
: "AFF123", // optional
"revenue"
: "250.00", // 120*1quantity + 120*1quantity + 10shipping
"tax"
: "75.00", // 250 * (1-(100%/120%))
"shipping"
: "10.00", // Includes Tax: 8.33 + tax = 10.00
"shippingMethod"
: "UPS Ground", // optional
"date"
: "2014-01-01", // optional
"coupon"
: "VOUCHER1234", // optional - aka transactionPromoCode or transactionVoucher
"couponDiscount"
: "0.00", // optional how much reduced by, not percentage
"paymentType"
: "Direct Debit", // optional - can also be used for CreditCard, Paypal, etc
"type"
: "Monthly Subscription", // optional
"subTotalIncludeTax"
: "true" // Indicates whether TransactionTotal includes tax
},
"products": [{
"id"
: "BS-123", // sku
"name"
: "BLUE Shoes",
"category"
: "Shoes",
"brand"
: "Nike",
"variant"
: "Blue",
"coupon"
: "SHOESALE",
"price"
: "120.00", // Includes Tax: 100+tax = 120.00
"quantity"
: "1"
},{
"id"
: "RS-123", // sku
"name"
: "RED Shoes",
"category"
: "Shoes",
"brand"
: "Nike",
"variant"
: "Red",
"coupon"
: "SHOESALE",
"price"
: "120.00", // Includes Tax: 100+tax = 120.00
"quantity"
: "1"
}],
}
},
// CustomDimensions persistence can be userScope=6months, sessionScope=30mins or hitScope=pageScope
"user.id"
: "12345", // cd001: userScope -auth.user.getId
"cart.id"
: dataLayer.ecommerce.checkout.actionField.id, // cd014: sessionScope
//,"containerVersion"
: "", // cd005: reserved slot for userScope {{containerVersion}}
// CustomMetrics type can be integerType, currencyType (decimals), timeType
"cart.total": dataLayer.ecommerce.checkout.actionField.revenue, // cm002: currencyType - ecomm_totalvalue
"visitorLifetimeValue": "250.00", // cm001: currencyType - Includes Tax: ($100*2+$10)+tax = $250.00
"firstPurchaseDate": new Date("January 01 2014 23:59:59"), // cd007: userScope customer lifetime
// Adwords Dynamic Remarketing dimensions for product image IDs
// support.google.com/adwords/answer/2476691?hl=en & support.google.com/adwords/answer/3103357?hl=en
// & support.google.com/tagmanager/answer/3002580?hl=en
"google_tag_params": {
"ecomm_pagetype": "purchase", // cd015:home|category|product|cart|purchase|other {{page.category.pageType}}
"ecomm_paymentstep": dataLayer.ecommerce.purchase.actionField.option,//cd016: checkout > login > delivery >
billing > payments > complete
"ecomm_prodid"
: [""], // cd017: e.g. ["sku_111","sku_222"] {{ecommerce.products[n].id}}
"ecomm_totalvalue"
: dataLayer.ecommerce.purchase.actionField.revenue, // cm002: £100
"ecomm_pname"
: [""], // cd018: optional {{ecommerce.products[n].name}}
"ecomm_pcat"
: [""], // cd019: optional {{ecommerce.products[n].category}}
"ecomm_rec_prodid"
: [""], // cd020: e.g. shoe shine {{ecommerce.recommendation[n].id}}
// Auth logged-in variables
//"user.id"
: "", // cd001:WARNING never use userId, cartId or sessionId for remarketing
"user_isRegistered"
: "true", // cd002: y|n users has an account?
"user_isLoggedIn"
: "true", // cd003: y|n users is signed-in?
"user_isReturnCustomer"
: "true", // cd004: y|n users has transacted already?
"user_memberType"
: "free member", // cd006: Free Member, Premium Member or Enterprise Member
"user_memberTypeClass"
: "international member", // cd007: sub-types of memberClass
"user_ageRange"
: "20-25", // cd008: Age range
"user_gender"
: "male", // cd009: Gender
"user_customerQualityScore"
: "high", // cd010: Customer Quality Score - High, Med, Low
"user_highSpenderScore"
: "high", // cd011: High Spender Score - High, Med, Low
"user_loyaltyScore"
: "high", // cd012: Loyalty Score - High, Med, Low
"session_testVariant"
: "version a - offer x" // cd013: combine A/B testing offer with remarketing
//, "session_type"
: "returning",//cd000: new|returning 30min session native GA field UserType
},
// Trigger transaction submission to GA via GTM
"event"
: "header_datalayer_loaded", // Used to trigger dataLayer dependencies
"event"
: "transaction"
});
</script>
<!-- End Google Tag Manager Data Layer -->
</HEAD>

44

<BODY>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-xxxx" height="0" width="0"
style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-xxxx');
</script>
<!-- VERSION: GTM_October_v1 -->
<!-- WEBSITE: clientdomain.com -->
<!-- CATEGORY: ecommerce -->
<!-- MARKET: UK -->
<!-- GTM-LIVE:UA-00000-1 | GTM-DEV:UA-00000-2 :: rolledupTracker
-->
<!-- GTM-LIVE:UA-111111-1 | GTM-DEV:UA-111111-2 :: localCountryTracker -->
<!-- Replace GTM-xxxx with GTM-LIVE for live, or GTM-DEV for dev -->
<!-- End Google Tag Manager -->

IMPORTANT: Do not use commas in number (e.g. 1,000 change to 1000)
"transactionTotal": "1,000.00", // comma error
Should be:
"transactionTotal": "1000.00",
Note1: Do NOT use null for empty text values
"transactionAffiliation": null, // value error
Instead use undefined instead:
"transactionAffiliation": undefined,
Note2: For empty numbers, ensure these are in Quotation marks to avoid a JS error:
"transactionTotal": , // JS error
These are fine:
"transactionTotal": undefined,
Note3: Both these methods are valid for numbers, but due to JS errrors with null numbers - it is safer to
standardise use quotation marks on populated number values e.g. "100.00":
"transactionTotal": 100.00,
"transactionTotal": "100.00", // safer, but not JSON compliant
Tip: JS trick - you can convert a string to number by simply subtracting 0 e.g:
var myNum = dataLayer.transactionTotal - 0;
Help page:
ï‚· support.google.com/tagmanager/answer/3002596?hl=en
ï‚· support.google.com/tagassistant/answer/3207128?hl=en#dl_quoted
ï‚· jsonlint.com

45

Social Measurement: Social actions buttons
There are some well written instructions on GTM social tracking by Simo Ahava here &
the official Google dataLayer names for social here.
In order to track Like & Tweet buttons on the blog and item pages GA measurements
need to be triggered, for example: ['_trackSocial', socialNetwork, socialAction,
opt_target, opt_pagePath]

In order to track these social interactions the buttons just add customHTML triggered
on gtm.dom ready
Facebook (JavaScript version)
<script>
FB.Event.subscribe("edge.create", function(targetUrl) {
dataLayer.push({
'event': 'social'
'socialNetwork': 'facebook',
'socialAction': 'like',
'opt_target': targetUrl, // optional
'opt_pagePath': window.location.pathname + window.location.search, // optional
'eventValue': parseInt(0.00)
});
});
</script>

Twitter (JavaScript version)
<script>
function trackTwitter(intent_event) {
if (intent_event) {
var opt_pagePath;
if (intent_event.target && intent_event.target.nodeName == "IFRAME") {
opt_target = extractParamFromUri(intent_event.target.src, "url");
}
dataLayer.push({
'event': 'social',
'socialNetwork': 'twitter',
'socialAction': 'tweet',
'opt_target': opt_target, // optional
'opt_pagePath': opt_pagePath, // optional
'eventValue': parseInt(0.00)
});
}
}
//Wrap event bindings - Wait for async js to load
twttr.ready(function (twttr) {
//event bindings
twttr.events.bind("tweet", trackTwitter);
});
</script>

Google+ (For Universal this is NOT needed for Legacy GA.js)
<script>
function sendPlus(targetUrl) {
dataLayer.push({
'event': 'social',
'socialNetwork': 'google',
'socialAction': '+1',
'opt_target': targetUrl.href, // optional
'opt_pagePath': location.pathname + location.search, // optional
'eventValue': parseInt(0.00)
});
};
</script>

See this Google documentation for details of the Facebook and Twitter API.
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingSocial#facebook
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingSocial#twitter

46

Facebook (Static Link version)
<a href="http://www.facebook.com/ClientDomain" target="_blank">
<img src="/images/social_network/icon_facebook.jpg">
</a>

Hardcoded onclick code would look like this...
<a href="http://www.facebook.com/ClientDomain" target="_blank"
onclick="dataLayer.push({'event':'social', 'socialNetwork':'facebook',
'socialAction': 'like', 'opt_target': location.href, 'opt_pagePath':
location.pathname + location.search, 'eventValue':parseInt(0.00)});">
<img src="/images/social_network/icon_facebook.jpg">
</a>

Pinterest

For Pinterest see this help page:
http://www.lunametrics.com/blog/2012/03/12/tracking-pinterest-event-tracking/

47

Please note: for ShareThis no action is needed as this can be added via GTM:
<!-- GTM will try to use
http://w.sharethis.com/button/buttons.js else
https://ws.sharethis.com/button/buttons.js
-->
<script
src="{{lookup_HTTP_protocol_to_sharethis.com}}/button/buttons.js">
</script>
<script>
var switchTo5x = true;
// var __st_loadLate = true; // Wait for dom.content
</script>
<script>
stLight.options({
"publisher": "YOUR-PROFILE-ID", // Change this to your ID
"version": "5x",
// "doNotHash": false,
// "doNotCopy": false,
// "hashAddressBar": false,
"publisherGA": "{{setting_ga_id}}",
"tracking": true // enable GA tracking
});
</script>

Help page:
http://support.sharethis.com/customer/portal/articles/446390-google-analytics

Please note: for AddThis no action is needed as this can be added via GTM in GA
classic using:
<script>
var addthis_config = {
"data_ga_property": "{{settings_ga_id}}",
"data_ga_social": true,
"event": "donewith_addthis_tracker"
};
</script>
<script src="//s7.addthis.com/js/250/addthis_widget.js#pubid=YOURPROFILE-ID">
</script>
Help page:
http://support.addthis.com/customer/portal/articles/381260-google-analytics-integration#how

48

For AddThis GA universal - you can use bind to ID="addthis_button_preferred_[n]". See
the example here.

<!-- AddThis Script to bind onclick GTM social event based on ID present on the page -->
<script type="text/javascript">
window.dataLayer = window.dataLayer || [];
// FACEBOOK
document.getElementById("addthis_button_preferred_1").onclick = function(){
window.dataLayer.push({
'event': 'social',
'socialNetwork': 'Facebook',
'socialAction': 'like',
'opt_target': document.getElementById("addthis_button_preferred_1").href,
// 'opt_pagePath': opt_pagePath, // optional
'eventValue': 0,
'socialButtonPosition': 'top'
});
};
// TWITTER
document.getElementById("addthis_button_preferred_2").onclick = function(){
window.dataLayer.push({
'event': 'social',
'socialNetwork': 'Twitter',
'socialAction': 'tweet',
'opt_target': document.getElementById("addthis_button_preferred_2").href,
// 'opt_pagePath': opt_pagePath, // optional
'eventValue': 0,
'socialButtonPosition': 'top'
});
};
// GOOGLE PLUS
document.getElementById("addthis_button_preferred_3").onclick = function(){
window.dataLayer.push({
'event': 'social',
'socialNetwork': 'Google+', // Changed from 'google'
'socialAction': '+1',
'opt_target': document.getElementById("addthis_button_preferred_3").href,
// 'opt_pagePath': opt_pagePath, // optional
'eventValue': 0,
'socialButtonPosition': 'top'
});
};
</script>

49


Documenti correlati


Documento PDF dev gtm guide v3 7
Documento PDF di mele mediucation 2016
Documento PDF som200 dev xi datasheet
Documento PDF ultimate guide to trading penny stocks
Documento PDF guida genitori 1
Documento PDF john person complete guide to technical trading tactics


Parole chiave correlate