-
Notifications
You must be signed in to change notification settings - Fork 28.4k
Adding <GoogleTagManager> component to @next/third-parties #56106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 23 commits
733a173
022a773
21551de
d6d7944
2a74723
52ca4e2
ee5969f
63ddaf7
fee976a
07a8f15
ff6b24f
e8dd1cc
33db325
8f143c8
ed30df7
7f9cf1c
e5473fc
5785971
9c2fd1f
49e29a6
3c9fc3f
f84dcae
ae0463b
4b6b00c
86d1a29
1e3031d
0fe8864
0a3c63b
fbd24de
fa14ece
0ecadb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
'use client' | ||
// TODO: Evaluate import 'client only' | ||
import React from 'react' | ||
import Script from 'next/script' | ||
|
||
declare global { | ||
interface Window { | ||
dataLayer?: Object[] | ||
[key: string]: any | ||
} | ||
} | ||
|
||
type GTMParams = { | ||
gtmId: string | ||
dataLayer: string[] | ||
dataLayerName: string | ||
auth: string | ||
preview: string | ||
} | ||
|
||
let currDataLayerName = 'dataLayer' | ||
|
||
export function GoogleTagManager(props: GTMParams) { | ||
const { gtmId, dataLayerName = 'dataLayer', auth, preview, dataLayer } = props | ||
|
||
currDataLayerName = dataLayerName | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this pattern is edge-case free. When you render this component it will use the initial dataLayer prop to instantiate the script by id. Then afterwards any changes to the dataLayer prop will not be reflected in teh gtm script but will alter this module scoped variable. The If it is true that you can't hot-update the datalayer in GTM (meaning you need to just pick it at the start of the app runtime and never change it) then we should align the module global to only update when the gtm script will actually run which is just once one hte first render. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense! I have updated the code to only modify |
||
|
||
const gtmLayer = dataLayerName !== 'dataLayer' ? `$l=${dataLayerName}` : '' | ||
const gtmAuth = auth ? `>m_auth=${auth}` : '' | ||
const gtmPreview = preview ? `>m_preview=${preview}>m_cookies_win=x` : '' | ||
|
||
return ( | ||
<> | ||
<Script | ||
id="_next-gtm-init" | ||
dangerouslySetInnerHTML={{ | ||
__html: ` | ||
(function(w,l){ | ||
w[l]=w[l]||[]; | ||
w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'}); | ||
${dataLayer ? `w[l].push(${JSON.stringify(dataLayer)})` : ''} | ||
})(window,'${dataLayerName}');`, | ||
}} | ||
></Script> | ||
huozhi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<Script | ||
id="_next-gtm" | ||
src={`https://www.googletagmanager.com/gtm.js?id=${gtmId}${gtmLayer}${gtmAuth}${gtmPreview}`} | ||
></Script> | ||
</> | ||
) | ||
} | ||
|
||
export const sendGTMEvent = (data: Object) => { | ||
if (window[currDataLayerName]) { | ||
window[currDataLayerName].push(data) | ||
} else { | ||
console.warn(`dataLayer ${currDataLayerName} does not exist`) | ||
huozhi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { default as GoogleMapsEmbed } from './GoogleMapsEmbed' | ||
janicklas-ralph marked this conversation as resolved.
Show resolved
Hide resolved
huozhi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
export { default as YouTubeEmbed } from './YouTubeEmbed' | ||
export { GoogleTagManager, sendGTMEvent } from './gtm' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
'use client' | ||
|
||
import React from 'react' | ||
import { GoogleTagManager, sendGTMEvent } from '@next/third-parties/google' | ||
|
||
const Page = () => { | ||
const onClick = () => { | ||
sendGTMEvent({ event: 'buttonClicked', value: 'xyz' }) | ||
} | ||
|
||
return ( | ||
<div class="container"> | ||
<GoogleTagManager gtmId="GTM-XYZ" /> | ||
<h1>GTM</h1> | ||
<button id="gtm-send" onClick={onClick}> | ||
Click | ||
</button> | ||
<GoogleTagManager gtmId="GTM-XYZ" /> | ||
</div> | ||
) | ||
} | ||
|
||
export default Page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can do this in a separate PR, but we should update the GTM example in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the double There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had thought the same in the beginning, but I recall @janicklas-ralph mentioning that it is was deliberate to test that the behavior if an identical GTM containers is included by accident @janicklas-ralph Can you clarify, and if so, add a note here in a future PR? (not urgent) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from 'react' | ||
import { GoogleTagManager, sendGTMEvent } from '@next/third-parties/google' | ||
|
||
const Page = () => { | ||
const onClick = () => { | ||
sendGTMEvent({ event: 'buttonClicked', value: 'xyz' }) | ||
} | ||
|
||
return ( | ||
<div class="container"> | ||
<GoogleTagManager gtmId="GTM-XYZ" /> | ||
<h1>GTM</h1> | ||
<button id="gtm-send" onClick={onClick}> | ||
Click | ||
</button> | ||
<GoogleTagManager gtmId="GTM-XYZ" /> | ||
</div> | ||
) | ||
} | ||
|
||
export default Page |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename
gtmId
to justid
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally had it as id but since I made it into a component, I am accepting the GTM params as props
<GoogleTagManager gtmId="GTM_XYZ" />
In this case id might clash with HTML id so I changed it to gtmID