Shopify pixels, Shopify Consent Banner and Google consent mode V2

Here is a topic that I’ve been navigating on for a while now and came up with a solution that works for now but want to check with other brilliant minds here and potentially improve on it.

There are many 3rd party cookie consent banner apps out there that claim to have nailed this in my experience these are false claims or requires merchants to spend even more time setting everything up properly. Bottom line is: 3rd party consent apps do not offer an out of the box solution for this problem.
At the end of the day I am all about using native Shopify tools as much as possible.

Problem

The native GA integration via Google and Youtube sales channel + the Shopify consent banner do not work with Google consent Mode v2.

The first issue is that the GA (from native google sales channel) is using cookie, so naturally the Shopify consent banner will block cookies prior to user interacting with the Shopify consent banner. Which in effect means that the first page load is never tracked. When users decide to interact with the consent banner there are a few options:

  • User accepts all tracking (G111)
  • User declines all tracking (G100)
  • User accepts some tracking (G101 or G110)

With native GA and Shopify consent banner - none of the above get the G*** parameter assigned - which is the problem.

Solution

The solution is to move the merchant to GTM or course. Why? - you might ask
Well to start with, GTM does not use cookies and we can load GTM container without user consent.

Great, but now we have another set of problems.
By default, Shopify pixel does not sent the G*** parameters to GTM so we need Shopify pixel to handle that. Thanks to Shopify customerPrivacy API we can rightfully do that in Shopify pixel where we listen from events coming from Shopify consent banner and then push events to GTM with the selected consent from the banner, while assigning the correct G*** tag.

Furthermore, we can send the G*** tag to GTM on the initial page load (before customers interact with the banner) - and yes, this is legit as we do only need to send the G111 parameter with a page view event so it complies with GDPR. It basically works the same as a click event. You don’t need a consent from customers for the click events, right?

After users interact with the consent banner and choose their preference, we then update the G*** tag based on their preference and send that to GTM, basically solving the following issues:

  • Track customers first interaction with the site by emitting an empty page_view event to GTM
  • Update the consent status right after they interact with the consent banner(not on the next page load)
  • Correctly assign the consent and G*** parameter for GTM base don user selection
  • Stay Shopify native and not use a 3rd party app

The above work like a charm even though it was a bumpy road to piece everything together.
I have ran this with the legal teams of a couple of merchants and checked with the marketing teams of even more merchants and they are all onboard with the solution.
However, my questions are:

  1. Is anyone handling this in a more holistic way?
  2. Currently there is a lot of discrepancy between customerPrivacy API and google (listed below) - are there any plans to have the API be more aligned with Google’s consent mode v2? (we have Microsoft now that onboarded the same framework too)
  3. Anyone who is serious about their business would most likely want a setup like this. However, in reality, this setup takes about 8-12 hours to implement and test. A lot of merchants do not have availability to such dev resources so they will be exposed to GDPR claims.

For reference here is the Shopify customerPrivacy api uses:

{
     "analyticsProcessingAllowed": boolean,
     "marketingAllowed": boolean,
     "preferencesProcessingAllowed": boolean,
     "saleOfDataAllowed": boolean,
 }

And here is what the Google Consent mode V2 uses

{
  'ad_storage': 'denied',
  'ad_user_data': 'denied',
  'ad_personalization': 'denied',
  'analytics_storage': 'denied'
}

Below are a couple of useful resources that i have used to puzzle everything together.

The Apps Developed by the end-party (google as an example) do code their pixels to relay the proper consent.

Otherwise you could create a web pixel that takes the shopify values and send them as a gtag version something like…

// Subscribe to customer privacy consent collected events to update the status
api.customerPrivacy.subscribe('visitorConsentCollected', (event) => {
    customerPrivacyStatus = event.customerPrivacy;
    // send gtag update
});
// PAGE VIEWED EVENT
analytics.subscribe('page_viewed', (event) => {
    // Prepare payload with event name and customer privacy status
    const payload = {
        eventName: event.name,
        customerPrivacyStatus: customerPrivacyStatus,
    };
    console.log("consent_state: ", payload);
    // send gtag value
});

Thanks for engaging with the post.

The issue is the end-party app only supports GA integration, not GTM.

On a basic level what you described works (as per shopify documenation) but that is not enough. In order to send the correct privacy parameters from Shopify Pixel to GTM it requires additional logic and mapping, for consent to work in GTM - hence my drive for posting this.

You see, the issue is that the customerPrivacyStatus object looks something like this:

 {
  "analyticsProcessingAllowed": boolean,
  "marketingAllowed": boolean,
  "preferencesProcessingAllowed": boolean,
  "saleOfDataAllowed": boolean,
}

However as mentioned in the original post, GTM expects something else.

agreed - i’m saying you’d have to get the shopify status, map it, and update google

{
     "analyticsProcessingAllowed": boolean, // = analytics_storage
     "marketingAllowed": boolean, // = ad_storage
     "preferencesProcessingAllowed": boolean, // = ad_personalization
     "saleOfDataAllowed": boolean, // = ad_user_data
 }

pass that mapped status to:

gtag('consent', 'default', {
  'ad_storage': 'denied', // mapped status
  'ad_user_data': 'denied', // mapped status
  'ad_personalization': 'denied', // mapped status
  'analytics_storage': 'denied' // mapped status
});

or when changed

 gtag('consent', 'update', {
  'ad_storage': 'denied', // mapped status
  'ad_user_data': 'denied', // mapped status
  'ad_personalization': 'denied', // mapped status
  'analytics_storage': 'denied' // mapped status
});