# Google Consent Mode with Piwik PRO Consent & Tag Manager

**URL:** <https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426>\
**Category:** Privacy\
**Created:** [January 5, 2024, 9:17am UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426 "2024-01-05T09:17:53Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thomas\_Anode\_FR](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/thomas_anode_fr/32/1425_2.png) [@Thomas\_Anode\_FR](https://community.piwik.pro/u/Thomas_Anode_FR)\
**Post date:** [January 5, 2024, 9:17am UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/1 "2024-01-05T09:17:53Z")

</div>

Hello,

We’re using Piwik PRO Consent & Tag Managers, and we are running ads with Google Ads. We’re using the built-in Google Ads conversion & remarketing tags.

As Google announced the release of its new Consent Mode, it’s clear that this is will soon be mandatory for advertisers to use it (by March 2024): [Google announces Consent Mode v2 - What does it mean?](https://cookieinformation.com/resources/blog/google-announces-consent-mode-v2/).

I don’t think Piwik PRO is a certified Google CMP partner: [https://cmppartnerprogram.withgoogle.com/](https://cmppartnerprogram.withgoogle.com/). How can I implement Google Consent Mode using Piwik PRO Consent & Tag Managers?

Thank you very much!

---

<div class="post-metadata">

**Author:** ![Thomas\_Anode\_FR](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/thomas_anode_fr/32/1425_2.png) [@Thomas\_Anode\_FR](https://community.piwik.pro/u/Thomas_Anode_FR)\
**Post date:** [January 17, 2024, 9:05am UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/2 "2024-01-17T09:05:46Z")

</div>

**Update**  
I used Google’s documentation: [Administrar la configuración de consentimiento (Web) &nbsp;|&nbsp; Security and Privacy hub &nbsp;|&nbsp; Google for Developers](https://developers.google.com/tag-platform/security/guides/consent).

By following gtag.js method, you should be able to install Consent Mode with Piwik PRO Tag & Consent Managers. Make sure you trigger the tags in the correct order: default values first.

You can verify your implementation following these instructions: [Manage consent settings (web) &nbsp;|&nbsp; Security and Privacy hub &nbsp;|&nbsp; Google for Developers](https://developers.google.com/tag-platform/security/guides/consent#verify_consent_settings).  
I personally used the Network tab & Google Tag Assistant to check my setup.

I hope this will help!

---

<div class="post-metadata">

**Author:** ![romainproximity](https://avatars.discourse-cdn.com/v4/letter/r/2bfe46/32.png) [@romainproximity](https://community.piwik.pro/u/romainproximity)\
**Post date:** [January 17, 2024, 4:34pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/3 "2024-01-17T16:34:05Z")

</div>

Hello @Thomas_Anode_FR  
Did you have a look at this :

> **[Google consent mode integration | Piwik PRO help center](https://help.piwik.pro/support/integrations/google-consent-mode-integration/)**
>
> From November 2020, Google ads are displayed only to visitors who have consented to analytics and advertising cookies. They won’t pop up if the visitor hasn’t given their consent. Google relies on two consent mechanisms: IAB TCF 2.0 and Google...

---

<div class="post-metadata">

**Author:** ![Thomas\_Anode\_FR](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/thomas_anode_fr/32/1425_2.png) [@Thomas\_Anode\_FR](https://community.piwik.pro/u/Thomas_Anode_FR)\
**Post date:** [January 17, 2024, 4:46pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/4 "2024-01-17T16:46:10Z")

</div>

Hello @romainproximity,

I did, but I think that following Google’s guidelines is better. The main reason is that it clearly invites you to set default values to “denied” first. It is not the case in this Piwik PRO’s tutorial: it’s only update commands.

Additionally, Google’s guidelines integrate the new parameters “ad\_user\_data” and “ad\_personalization”. I think Piwik PRO documentation would benefit from a little update. 🙂

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [January 17, 2024, 5:01pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/5 "2024-01-17T17:01:24Z")

</div>

> [@Thomas\_Anode\_FR](#):
>
> I think Piwik PRO documentation would benefit from a little update.

Hey everyone, sorry for not responding earlier - we are working on an update 🫡.

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [February 1, 2024, 10:50am UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/6 "2024-02-01T10:50:15Z")

</div>

> **[Google consent mode v2 integration | Piwik PRO help center](https://help.piwik.pro/support/integrations/google-consent-mode-v2-integration/)**
>
> According to Google’s policy, Google ads are displayed only to visitors who have consented to analytics and advertising cookies. They won’t pop up if the visitor hasn’t given their consent. Google relies on two consent mechanisms: IAB TCF 2.2 and...

---

<div class="post-metadata">

**Author:** ![christophe.henaff](https://avatars.discourse-cdn.com/v4/letter/c/8c91f0/32.png) [@christophe.henaff](https://community.piwik.pro/u/christophe.henaff)\
**Post date:** [February 8, 2024, 4:36pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/7 "2024-02-08T16:36:24Z")

</div>

Hi @anthonybartczak ,  
The first step to integrate Google Consent Mode v2, with all the denied default.  
It must be on the webpages code, or can it be a tag in Tag Manager ?  
Thanks for your help,

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [February 8, 2024, 5:46pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/8 "2024-02-08T17:46:03Z")

</div>

Hi @christophe.henaff,

In my opinion ([and Google’s documentation mentions this method](https://developers.google.com/tag-platform/security/guides/consent?hl=pl#tracking_consent_state)) it’s best to embed the defaults directly in your website, before any tag managment or tracking tool is loaded. It’s the safest way because it skips potential issues with 3rd party tools.

---

<div class="post-metadata">

**Author:** ![loldenburg](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/loldenburg/32/965_2.png) [@loldenburg](https://community.piwik.pro/u/loldenburg)\
**Post date:** [March 5, 2024, 6:48pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/9 "2024-03-05T18:48:56Z")

</div>

I think any TMS should be capable of setting Consent defaults, even Piwik’s.

And maybe I misunderstand how Piwik’s Consent Manager works, but [Google consent mode v2 integration | Piwik PRO help center](https://help.piwik.pro/support/integrations/google-consent-mode-v2-integration/?pk_vid=d4dc5cfb794788b31709663257ed7630) mentions we should update the Consent Manager defaults when the Event is `stg.consentDecisionMade`.

But doesn’t that apply only to the rare cases when somebody first gives their consent (or even rarer, when they update consent)?

=\> If we only use that `stg.consentDecisionMade` Event, there will be no Consent given for any Pageviews where there was no interaction with the Consent Manager (=99% of Pageviews)…

The documentation is missing the crucial info that the update command needs to be fired on every pageview (or that the Consent “default” settings need to reflect the user’s current consent state on every page).

Last question:  
When I try to get {{ Consents }} via a Custom HTML Tag, it always refers to `window.sevenTag.getVariableValue('Consents', 3)`. This `3` refers to t.variables[3][“Consents”] which sometimes contains a filled `Consents` object, but also sometimes not…  
 ![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/f/f5471efb1acbb05956cf49999c3342b2fe1fbcb7.png)

E.g. here (trying to receive “Consents” with the `stg.consentDecisionMade` Event: Consents.current\_state is just an empty object → setting Consent Mode via the `googleConsentModeMapping` function from the documentation fails (everything gets “denied”…

![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/6/62c66a25dd41c029b14d162383e31cc42a3146d0.png)

Why does a reference to a Variable not always get the latest version of it? (=which would contain the correct values)  
 ![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/e/e497436a30e302aec73d9ad02031a2f215321a0d.png)

---

<div class="post-metadata">

**Author:** ![loldenburg](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/loldenburg/32/965_2.png) [@loldenburg](https://community.piwik.pro/u/loldenburg)\
**Post date:** [March 5, 2024, 7:04pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/10 "2024-03-05T19:04:39Z")

</div>

Looking at this again, it seems like PP TM, when 'eval’ing the Custom HTML Tag (with all comments, yikes, performance anyone?!), injects the INDEX of the data layer event that triggered the current tag into the `window.sevenTag.getVariableValue('Consents', INDEX);`call.

So if a tag has multiple triggers (like `stg.pageView` OR `stg.consentDecisionMade`, the value counts that was in the data layer when the tag was first called…

So if `stg.pageView` is the 3rd event (INDEX = 3) and `stg.consentDecisionMade` the 22nd (INDEX = 22), Piwik TM will still get the data of the `Consents` variable as it existed when the 3rd event happened…

So when somebody updates their consent level, this will never make it to the Google Consent Mode update as it will “update” it based on data layer INDEX 3 again (when Consent still did not exist)…

That is totally not how I expect a Variable reference to work. In GTM, it always takes the last value… I will have to re-visit quite some code now that I found this out…

I will replace Variable reference by this manual call now which always gets the latest version of a Variable:

`window.sevenTag.getVariableValue('Consents', dataLayer.length); `

But this should not be necessary…

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [March 5, 2024, 7:28pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/11 "2024-03-05T19:28:44Z")

</div>

> [@loldenburg](#):
>
> I think any TMS should be capable of setting Consent defaults, even Piwik’s.

It’s not about ability, it’s just recommended. See my answer here:

> [@Google Consent Mode: analytics\_storage denied](https://community.piwik.pro/t/google-consent-mode-analytics-storage-denied/3405/17):
>
> That was one of the reasons why we didn’t include the defaults in the code. We didn’t want to skip the defaults part in case there is a failure with the Piwik PRO container (e.g. outage, blocking) We wanted them (the defaults) to be on top of any potential tool that could either make use of them or modify them. As you’ve mentioned - it’s of course possible to add those in the integration tag but we can’t really advise on doing so because of the mostly asynchronous manner of Piwik PRO Tag Man…

> [@loldenburg](#):
>
> And maybe I misunderstand how Piwik’s Consent Manager works, but [Google consent mode v2 integration | Piwik PRO help center](https://help.piwik.pro/support/integrations/google-consent-mode-v2-integration/?pk_vid=d4dc5cfb794788b31709663257ed7630) mentions we should update the Consent Manager defaults when the Event is `stg.consentDecisionMade`.
> 
> But doesn’t that apply only to the rare cases when somebody first gives their consent (or even rarer, when they update consent)?
> 
> =\> If we only use that `stg.consentDecisionMade` Event, there will be no Consent given for any Pageviews where there was no interaction with the Consent Manager (=99% of Pageviews)…

And also the page view event  
 ![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/e/e13f4242abf6a2510e7f40849ef10d726249e7f5.png)

---

<div class="post-metadata">

**Author:** ![loldenburg](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/loldenburg/32/965_2.png) [@loldenburg](https://community.piwik.pro/u/loldenburg)\
**Post date:** [March 5, 2024, 7:31pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/12 "2024-03-05T19:31:47Z")

</div>

“It’s not about ability, it’s just recommended.”  
=\> I understand that it is only your recommendation, but I think a TMS is precisely there to avoid such stuff having to go on a website, so it is weird to get such a recommendation from a TMS vendor…

“And also the page view event”  
=\> What I wrote is: If I use both pageview and consentDecisionMade, the content of the Consents variable that is evaluated in the Custom HTML tag is always based on the first event on the page that triggered the tag (=the pageview, when we did not have consent yet).

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [March 5, 2024, 7:34pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/13 "2024-03-05T19:34:08Z")

</div>

> [@loldenburg](#):
>
> So if `stg.pageView` is the 3rd event (INDEX = 3) and `stg.consentDecisionMade` the 22nd (INDEX = 22), Piwik TM will still get the data of the `Consents` variable as it existed when the 3rd event happened…
> 
> So when somebody updates their consent level, this will never make it to the Google Consent Mode update as it will “update” it based on data layer INDEX 3 again (when Consent still did not exist)…

I’m not sure what you mean here. Edit: let me have a look again.

![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/9/9fa13258a45a6bf4492bca6a71b0bf2808ba889f.png)  
 ![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/1/17907d34c12ee6fdb2a617ad3ed42905378b57ce.png)

@loldenburg do you mean changing the consent decision after the initial one was given?

---

<div class="post-metadata">

**Author:** ![loldenburg](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/loldenburg/32/965_2.png) [@loldenburg](https://community.piwik.pro/u/loldenburg)\
**Post date:** [March 5, 2024, 7:37pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/14 "2024-03-05T19:37:18Z")

</div>

This is what finally works now (took me 4 hours to build sth that should take 30 minutes):

One Custom HTML Tag, fired upon pageView and stg.consentDecisionMade:

```auto
<script>
    // fired this upon stg.pageView and stg.consentDecisionMade
    window.gtag = window.gtag || function(){dataLayer.push(arguments)};
    /*
    Validate: Check Google Ads Tag and look for these parameters:
    - gcs: G110 => Ads granted, Analytics denied
    - gcd: 13r3q3r3r5 => denied by default and granted after update, except analytics storage
     */
    if (!window.googleConsentModeMapping) { // initialize the function only once per page
        function googleConsentModeMapping(consents) {
            var consentLevels = window.sevenTag.getVariableValue('Consents', dataLayer.length-1);
            TMSHelper.console("Consent Levels: ", consentLevels);
            if (consentLevels) {
                var consObj = {};
                Object.keys(consents).forEach(function(consent) {
                    consObj[consent] = (consentLevels.current_state[consents[consent]] === 1) ? 'granted' : 'denied';
                });
                gtag('consent', 'update', consObj);
            }
        }
        // set default consent values for the page, they are directly updated afterwards and when Consents are given or change
        gtag('consent', 'default', {
            'ad_storage': 'denied',
            'ad_user_data': 'denied',
            'ad_personalization': 'denied',
            'analytics_storage': 'denied'
        });
    }

    googleConsentModeMapping({
            "ad_storage": "custom_consent", // "custom_consent" is the value which we also use to fire Google Ads Pixels
            "ad_user_data": "custom_consent",
            "ad_personalization": "custom_consent",
            "analytics_storage": "denied" // we don't use Google Analytics, so we don't need to give analytics storage rights
    });
</script>

```

I needed to use  
`window.sevenTag.getVariableValue('Consents', dataLayer.length-1);`,  
otherwise the stg.consentDecisionMade Event never leads to an actual “update” of the google consent levels because it always refers to `window.sevenTag.getVariableValue('Consents', 3);` =\> 3 the INDEX of the pageView Event which first fired the Tag…

---

<div class="post-metadata">

**Author:** ![anthonybartczak](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/anthonybartczak/32/2430_2.png) [@anthonybartczak](https://community.piwik.pro/u/anthonybartczak)\
**Post date:** [March 5, 2024, 7:44pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/15 "2024-03-05T19:44:10Z")

</div>

> [@loldenburg](#):
>
> I needed to use  
> `window.sevenTag.getVariableValue('Consents', dataLayer.length-1);`,  
> otherwise the stg.consentDecisionMade Event never leads to an actual “update” of the google consent levels because it always refers to `window.sevenTag.getVariableValue('Consents', 3);` =\> 3 the INDEX of the pageView Event which first fired the Tag…

Maybe I’m missing something here but I don’t think that is true. As an example, see the deanonymization tag:  
 ![image](https://europe1.discourse-cdn.com/flex005/uploads/piwikpro/original/2X/0/09e4cbc72331cd0ff6197ed08173586b5fdca04d.png)

The consent decision event I’ve sent before shows the same thing.

So which part I’m missing 😅?

---

<div class="post-metadata">

**Author:** ![loldenburg](https://dub1.discourse-cdn.com/flex005/user_avatar/community.piwik.pro/loldenburg/32/965_2.png) [@loldenburg](https://community.piwik.pro/u/loldenburg)\
**Post date:** [March 5, 2024, 8:22pm UTC](https://community.piwik.pro/t/google-consent-mode-with-piwik-pro-consent-tag-manager/3426/16 "2024-03-05T20:22:44Z")

</div>

Ok solved this (thx).  
The problem arose from

1. Defining the `googleConsentModeMapping`function in a way that it does not get redefined every time the Tag is triggered (by checking for `!window.googleConsentModeMapping` before defining it).
2. Checking for the `{{ Consents }}` variable INSIDE that function.

If we write `{{ Consents }}` in a tag, Piwik TM turns this into `window.sevenTag.getVariableValue('Consents', INDEX);` =\> the INDEX refers to the index of the dataLayer of the Event which first fired the Tag… So if “pageView” triggered the Tag and “pageView” was the 3rd Event, the index will be 3 =\> `window.sevenTag.getVariableValue('Consents', 3);`

Now if this is INSIDE the function, the function will use the value of the 3rd data layer event (pageView) even if the function is called later, e.g. on `stg.consentDecisionMade`. =\> Thus any future update of the tag will result in a reset to the Consent values at the state of the pageView =\> my problem.

So in short, I would have expected Piwik TM to not hard-write the value `3` into a function but instead use a dynamic function that always gets the latest variable value at runtime (like in GTM).

Anyway, the solution is:

- to take the {{ Consents }} out of the function
- add a another argument `consentLevels` to the function
- put {{ Consents }} into the function call at the end

=\> This seems to be the best compromise. We are not re-defining the function every time the Tag is called and we are still getting always the latest value.

```auto
<script>
    // fired on stg.pageView and stg.consentDecisionMade
    window.gtag = window.gtag || function(){dataLayer.push(arguments)};
    /*
    Validate: Check Google Ads Tag and look for these parameters:
    - gcs: G110 => Ads granted, Analytics denied
    - gcd: 13r3q3r3r5 => denied by default and granted after update, except analytics storage
     */
    if (!window.googleConsentModeMapping) { // initialize the function only once per page
        function googleConsentModeMapping(consents, consentLevels) {
            console.log("Consent Levels: ", consentLevels);
            if (consentLevels) {
                var consObj = {};
                Object.keys(consents).forEach(function(consent) {
                    consObj[consent] = (consentLevels.current_state[consents[consent]] === 1) ? 'granted' : 'denied';
                });
                gtag('consent', 'update', consObj);
            }
        }
        // set default consent values for the page, they are directly updated afterwards and when Consents are given or change
        gtag('consent', 'default', {
            'ad_storage': 'denied',
            'ad_user_data': 'denied',
            'ad_personalization': 'denied',
            'analytics_storage': 'denied'
        });
    }

    googleConsentModeMapping({
            "ad_storage": "custom_consent", // "custom_consent" is the value for "external media" which we also use to fire Google Ads Pixels
            "ad_user_data": "custom_consent",
            "ad_personalization": "custom_consent",
            "analytics_storage": "denied" // we don't use Google Analytics, so we don't need to give analytics storage rights
    }, {{ Consents }}); // the "Consents" variable needs to remain outside of the function because otherwise it will always contain the consent levels of when the tag was first called.
</script>
```
