You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am currently working on building out a consent manager feature and came across a few challenges integrating with the @analytics/google-tag-manager plugin. I've created some ("sketchy" - at best) workarounds which I am sharing below for feedback and suggestions on how to improve and especially on how to better incorporate this logic into the plugin itself.
Expected Behavior
I don't mind raising a P.R. and doing the work, as long as I have a clear path forward. Sorry for the long intro, but I'll break down the issue here:
Consent Mode v2 requires that default consents get initialized before any tags are read. See here. This ideally would mean that we've disabled the plugin. Which in turn means the gtag script is not injected into the DOM.
Currently there are no apis or mechanisms from what I can gather that enable us to tap into this event specifically: gtm.init_consent.
This event can be triggered declaratively (demonstrated in my workaround below).
No access to the actual script tag, no apis or a clean way of even referencing it in the DOM. Having a reference to the script itself opens up the option to set an event listener to fire when the script loads. Which is the hack that I came across.
Moreover, no exposed access to the internal gtag fn that is used to handle the page and track events under the hood. Or even better direct access to the dataLayer object.
UPDATE: I did notice a few options in the plugin source code that might allow a better dx, but will need to explore and likely requires either extending the current plugin or creating a custom plugin to handle the initial consent. I've documented this below in my examples accordingly.
Feature Request
Ideally an imperative way to initialize default consent scopes directly via the plugin's userConfig params.
At the least, I'd like to add an #id attribute to the script tag element which would allow us to grab a reference to the element itself. I've tested this locally directly in my node modules and this definitely works.
Without access to the script itself and having trouble targeting it via the src attribute, I've cobbled together this workaround:
Additonal Context
Grab a reference to the internal gtag function that gets set on the window when the plugin initializes.
Then we need to find a way to initialize the script before the plugin loads, because when the plugin loads it will begin to set tags and that will trigger the gtm.init event without the default consents.
exportconstGtagComponent=()=>{constanalytics=useAnalytics();// grab reference to script elementconstscriptElement: HTMLElement|null=typeofwindow!=='undefined'
? document.getElementById('gtag-script')
: null;consthandleScriptLoad=()=>{if((scriptElementasany)?.readyState==='loaded'){// set cookies in browser storagesetInitialCookies([...defaultCookies]);setInitialCookies([...adCookies],true);try{(windowasany).gtag=gtagFn((windowasany).dataLayer,'gtag');constgtag=gtagFn('dataLayer','gtag');// set cookies in gtm dataLayerif(typeofgtag==='function'){gtag?.('consent','default',{
...getCookies([...defaultCookies]),});gtag?.('consent','default',{
...getCookies([...adCookies]),});// set redaction cookie by defaultgtag?.('set',redactionCookie,true);}console.log('gtag initialized');if(getCookie(ANALYTICS_STORAGE_KEY)==='1'){analytics.plugins.enable('google-tag-manager');}}catch(error){console.error('Failed to initialize gtag:',error);}}else{console.warn('gtag script not yet loaded, waiting...');}};useEffect(()=>{if((scriptElementasany)?.readyState==='loaded'){console.log('found script element');handleScriptLoad();return;}return()=>{// remove script element from DOM - not sure if this is necessary.(scriptElementasHTMLScriptElement|null)?.remove();};}},[scriptElement]);return(<Scriptstrategy='lazyOnload'src={`https://www.googletagmanager.com/gtag/js?id=${env.NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID}`}// Replace with your Google Analytics IDid='gtag-script'onLoad={()=>{try{(windowasany).gtag=gtagFn((windowasany).dataLayer,'gtag');// Invoke gtagFn after script loads}catch(error){console.error('Error loading gtag',error);}}}/>);}
This is basically the complete work around, but I'll show how I've configured the rest to work including my analytics config
UPDATE: I just did some more digging into the plugins source, and noticed there is a way already defined to access the scriptLoad event internally.
And there is already a way to pass in a custom script -- Not sure how I missed these options in my first pass, but I will re-work my solution to see if i can take advantage of these apis.
The challenge now I guess is figuring out how to handle initial the consent before built in initialization method. I guess I can try extending the underlying plugin and see if that's the right strategy here.
So with this workaround I currently inject a script into the DOM when there is no consent cookie set, then i run through and initialize the consent for each applicable cookie. And then, once consent is set I can initialize the plugin by using the analytics.plugins.enable method if they've allowed analytics_storage.
I'd love to wrap some of this functionality into a plugin, but I've come up short each time I've tried. I'd be more than happy to do the work if someone wants to help me understand the right pattern here.
Description
I am currently working on building out a consent manager feature and came across a few challenges integrating with the @analytics/google-tag-manager plugin. I've created some ("sketchy" - at best) workarounds which I am sharing below for feedback and suggestions on how to improve and especially on how to better incorporate this logic into the plugin itself.
Expected Behavior
I don't mind raising a P.R. and doing the work, as long as I have a clear path forward. Sorry for the long intro, but I'll break down the issue here:
Consent Mode v2 requires that default consents get initialized before any tags are read. See here. This ideally would mean that we've disabled the plugin. Which in turn means the gtag script is not injected into the DOM.
Currently there are no apis or mechanisms from what I can gather that enable us to tap into this event specifically:
gtm.init_consent
.This event can be triggered declaratively (demonstrated in my workaround below).
No access to the actual script tag, no apis or a clean way of even referencing it in the DOM. Having a reference to the script itself opens up the option to set an event listener to fire when the script loads. Which is the hack that I came across.
Moreover, no exposed access to the internal gtag fn that is used to handle the
page
andtrack
events under the hood. Or even better direct access to thedataLayer
object.Feature Request
Ideally an imperative way to initialize default consent scopes directly via the plugin's
userConfig
params.At the least, I'd like to add an #id attribute to the script tag element which would allow us to grab a reference to the element itself. I've tested this locally directly in my node modules and this definitely works.
Without access to the script itself and having trouble targeting it via the
src
attribute, I've cobbled together this workaround:Additonal Context
gtm.init
event without the default consents.This is basically the complete work around, but I'll show how I've configured the rest to work including my analytics config
UPDATE: I just did some more digging into the plugins source, and noticed there is a way already defined to access the scriptLoad event internally.
The challenge now I guess is figuring out how to handle initial the consent before built in initialization method. I guess I can try extending the underlying plugin and see if that's the right strategy here.
Analytics Config:
So with this workaround I currently inject a script into the DOM when there is no consent cookie set, then i run through and initialize the consent for each applicable cookie. And then, once consent is set I can initialize the plugin by using the
analytics.plugins.enable
method if they've allowedanalytics_storage
.I'd love to wrap some of this functionality into a plugin, but I've come up short each time I've tried. I'd be more than happy to do the work if someone wants to help me understand the right pattern here.
Environment
The text was updated successfully, but these errors were encountered: