-
-
Notifications
You must be signed in to change notification settings - Fork 241
/
browser.js
132 lines (121 loc) · 4.43 KB
/
browser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
export const config = {
debug: false,
containerId: null,
dataLayerName: 'dataLayer',
dataLayer: undefined,
preview: undefined,
auth: undefined,
execution: 'async'
// assumesPageview: true,
}
let initializedDataLayerName;
/**
* Google tag manager plugin
* @link https://getanalytics.io/plugins/google-tag-manager
* @link https://developers.google.com/tag-manager/
* @param {object} pluginConfig - Plugin settings
* @param {string} pluginConfig.containerId - The Container ID uniquely identifies the GTM Container.
* @param {string} [pluginConfig.dataLayerName=dataLayer] - The optional name for dataLayer-object. Defaults to dataLayer.
* @param {string} [pluginConfig.customScriptSrc] - Load Google Tag Manager script from a custom source
* @param {string} [pluginConfig.preview] - The preview-mode environment
* @param {string} [pluginConfig.auth] - The preview-mode authentication credentials
* @param {string} [pluginConfig.execution] - The script execution mode
* @return {object} Analytics plugin
* @example
*
* googleTagManager({
* containerId: 'GTM-123xyz'
* })
*/
function googleTagManager(pluginConfig = {}) {
const defaultScriptSrc = 'https://www.googletagmanager.com/gtm.js'
// Allow for userland overides of base methods
return {
name: 'google-tag-manager',
config: {
...config,
...pluginConfig
},
initialize: ({ config }) => {
const { containerId, dataLayerName, customScriptSrc, preview, auth, execution } = config
if (!containerId) {
throw new Error('No google tag manager containerId defined')
}
if (preview && !auth) {
throw new Error('When enabling preview mode, both preview and auth parameters must be defined');
}
const scriptSrc = customScriptSrc || defaultScriptSrc;
if (!scriptLoaded(containerId, scriptSrc)) {
/* eslint-disable */
(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 : '',
p = preview ? '>m_preview=' + preview + '>m_auth=' + auth + '>m_cookies_win=x' : '';
if (execution) {
j[execution] = true;
}
j.src = `${scriptSrc}?id=` + i + dl + p;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', dataLayerName, containerId);
/* eslint-enable */
initializedDataLayerName = dataLayerName;
config.dataLayer = window[dataLayerName];
}
},
page: ({ payload, options, instance, config }) => {
if (typeof config.dataLayer !== 'undefined') {
config.dataLayer.push(payload.properties)
}
},
track: ({ payload, options, config }) => {
if (typeof config.dataLayer !== 'undefined') {
const { anonymousId, userId, properties } = payload
const formattedPayload = properties
if (userId) {
formattedPayload.userId = userId
}
if (anonymousId) {
formattedPayload.anonymousId = anonymousId
}
if (!properties.category) {
formattedPayload.category = 'All'
}
if (config.debug) {
console.log('dataLayer push', {
event: payload.event,
...formattedPayload
})
}
config.dataLayer.push({
event: payload.event,
...formattedPayload
})
}
},
loaded: () => {
const hasDataLayer = !!initializedDataLayerName && !!(window[initializedDataLayerName] && Array.prototype.push !== window[initializedDataLayerName].push)
return scriptLoaded(pluginConfig.containerId, pluginConfig.customScriptSrc || defaultScriptSrc) && hasDataLayer
},
}
}
export default googleTagManager
const regexCache = {}
/*
TODO add logic to make it impossible to load 2 plugins with the same container ID
[containerID]: pluginName
*/
function scriptLoaded(containerId, scriptSrc) {
let regex = regexCache[containerId]
if (!regex) {
const scriptSrcEscaped = scriptSrc
.replace(/^https?:\/\//, '')
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
regex = new RegExp(scriptSrcEscaped + '.*[?&]id=' + containerId)
regexCache[containerId] = regex
}
const scripts = document.querySelectorAll('script[src]')
return !!Object.keys(scripts).filter((key) => (scripts[key].src || '').match(regex)).length
}