UNPKG

3.62 kBJavaScriptView Raw
1const path = require('path')
2
3const defaults = {
4 dev: true,
5
6 id: null,
7 layer: 'dataLayer',
8 variables: {},
9
10 pageTracking: false,
11 pageViewEventName: 'nuxtRoute',
12
13 autoInit: true,
14 respectDoNotTrack: true,
15
16 scriptId: 'gtm-script',
17 scriptDefer: false,
18 scriptURL: 'https://www.googletagmanager.com/gtm.js',
19
20 noscript: false,
21 noscriptId: 'gtm-noscript',
22 noscriptURL: 'https://www.googletagmanager.com/ns.html'
23}
24
25module.exports = async function gtmModule (_options) {
26 const options = {
27 ...defaults,
28 ..._options,
29 ...this.options.gtm
30 }
31
32 // Don't include when run in dev mode unless dev: true is configured
33 if (this.options.dev && !options.dev) {
34 return
35 }
36
37 // Don't include when no GTM id is given
38 if (!options.id) {
39 // eslint-disable-next-line no-console
40 console.warn('[@nuxtjs/gtm] Disabling module because no id is provided!')
41 return
42 }
43
44 // Async id evaluation
45 if (typeof (options.id) === 'function') {
46 options.id = await options.id()
47 }
48
49 // Build query
50 const query = {
51 id: options.id,
52 // Default is dataLayer for google
53 l: options.layer !== 'dataLayer' ? options.layer : null,
54 ...options.variables
55 }
56 const queryString = Object.keys(query)
57 .filter(key => query[key] !== null && query[key] !== undefined)
58 .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
59 .join('&')
60
61 // doNotTrack polyfill
62 // https://gist.github.com/pi0/a76fd97c4ea259c89f728a4a8ebca741
63 const dnt = "(function(w,n,d,m,e,p){w[d]=(w[d]==1||n[d]=='yes'||n[d]==1||n[m]==1||(w[e]&&w[e].p&&e[e][p]()))?1:0})(window,'navigator','doNotTrack','msDoNotTrack','external','msTrackingProtectionEnabled')"
64
65 // Compile <script>
66
67 const initLayer = "w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'})" // deps: w,l
68
69 const injectScript = `var f=d.getElementsByTagName(s)[0],j=d.createElement(s);j.${options.scriptDefer ? 'defer' : 'async'}=true;j.src='${options.scriptURL + '?' + queryString}';f.parentNode.insertBefore(j,f);}` // deps: d,s
70
71 let script
72 if (options.autoInit) {
73 script = `(function(w,d,s,l){${initLayer};${injectScript})(window,document,'script','${options.layer}');`
74 if (options.respectDoNotTrack) {
75 script = `${dnt};window.doNotTrack||${script}`
76 }
77 } else {
78 script = `${dnt};(function(w,l){${initLayer}})(window,'${options.layer}');window.$initGTM=function(){(function(d,s){${injectScript})(document,'script');}`
79 }
80
81 // Add google tag manager <script> to head
82 this.options.head.script = this.options.head.script || []
83 this.options.head.script.push({
84 hid: options.scriptId,
85 innerHTML: script
86 })
87
88 // Prepend google tag manager <noscript> fallback to <body>
89 if (options.noscript) {
90 this.options.head.noscript = this.options.head.noscript || []
91 this.options.head.noscript.push({
92 hid: options.noscriptId,
93 pbody: true,
94 innerHTML: `<iframe src="${options.noscriptURL + '?' + queryString}" height="0" width="0" style="display:none;visibility:hidden" title="gtm"></iframe>`
95 })
96 }
97
98 // Disable sanitazions
99 this.options.head.__dangerouslyDisableSanitizersByTagID = this.options.head.__dangerouslyDisableSanitizersByTagID || {}
100 this.options.head.__dangerouslyDisableSanitizersByTagID[options.scriptId] = ['innerHTML']
101 this.options.head.__dangerouslyDisableSanitizersByTagID[options.noscriptId] = ['innerHTML']
102
103 // Register plugin
104 this.addPlugin({
105 src: path.resolve(__dirname, 'plugin.js'),
106 fileName: 'gtm.js',
107 ssr: false,
108 options
109 })
110}
111
112module.exports.meta = require('../package.json')