What's your biggest current challenge? Have your say in Community Polls along the right column.

Consent API: userCanBeTracked and getTrackingConsent in Liquid (server-side)

Consent API: userCanBeTracked and getTrackingConsent in Liquid (server-side)

NicoRi
Excursionist
15 0 4

Hey everyone,

 

since there's no hint in the docs that this is doable, I'm afraid I'll have to live with a No, but maybe there's some undocumented possibility to achieve this:

Is it possible to get the state of the Consent API in Liquid as well?

 

I want to load external tracking scripts only when tracking consent is given and/or tracking is generally allowed. Shopify's native Google Analytics implementation appears to do exactly this, for example. So I'd like to do something like this in my theme liquid:

{% if visitor.can_be_tracked %}
<script async src="https://url.to/trackingscript.js"></script>
{% endif %}

(this obviously doesn't work)

 

It is possible to muddle something together in JavaScript, essentially appending the <script> element dynamically to the DOM after querying the Consent API state, but I'd find it more elegant not to bother the browser/client at all with this.

 

Kind regards
Nico

Replies 3 (3)

azeller
Visitor
1 0 0

Hey Nico,

 

quick question. Did you ever solve this? One of our clients wants to implement server side tagging on their site and Shopify plugins seem to be very "idependent". Plugin A doesn't know about what plugin B is doing. So my problem is: How can I run a script depending on how the consent decision has been made? How did you solve this? Did you ever find a solution?

 

We might want to share the solution here for other people to find.

 

Andeas

NicoRi
Excursionist
15 0 4

Hey there,

 

I'm afraid not, we have to go the JavaScript way. What I did:

Somewhere below the {{ content_for_header }} line in theme.liquid (or, if you don't want to meddle in your theme's code, create a "Custom Liquid" block in your header or footer section), inserted this code:

<script>
    function msClarity() {
          userCanBeTracked = window.Shopify.customerPrivacy.analyticsProcessingAllowed();
          if(userCanBeTracked) {
            (function(c,l,a,r,i,t,y){
              c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
              t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
              y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
            })(window, document, "clarity", "script", "YOURTAGID");
          }
    }

    function bingConv() {
      userCanBeTracked = window.Shopify.customerPrivacy.thirdPartyMarketingAllowed();
      if(userCanBeTracked) {
        (function(w,d,t,r,u)
        {
          var f,n,i;
          w[u]=w[u]||[],f=function()
          {
            var o={ti:"YOURTAGID", enableAutoSpaTracking: true};
            o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")
          },
          n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function()
          {
            var s=this.readyState;
            s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)
          },
          i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)
        })
        (window,document,"script","//bat.bing.com/bat.js","uetq");
      }
    }

    window.Shopify.loadFeatures([
          {
            name: 'consent-tracking-api',
            version: '0.1',
          }
          ],
          function(error) {
            if (error) {
              throw error;
            }
            msClarity();
            bingConv();
            document.addEventListener('visitorConsentCollected', () => {
              msClarity();
              bingConv();
            });
    });
</script>

 A few notes:

  • I took MS Clarity and MS Bing Conversion tracking because they provide dynamically created <script> elements out of the box - if the tracking snippet you want to insert gives you a static <script src="..."></script> code, you'll have to convert that
  • Also, those two examples show the "Analytics allowed" vs "Third Party Marketing allowed" consent options
  • Since I didn't really dig deeper into Shopify's logic, I just went for "Each snippet function queries the window.Shopify.customerPrivacy.***allowed() for itself" way because I don't know if that's already set when the callback function is called. This can probably be solved in a more elegant way.
  • ...and the callback+event handling could probably also be more elegant, I was just too lazy to dig deeper into the Consent API logic regarding the point in time the callback is called/visitorConsentCollected is fired exactly. But it works: This way, when the Consent API is loaded on a page view where the visitor has already made their choice in the cookie banner before, it'll just call the bingAds() and MSClarity() functions, which will check if their respective consent has been given, and do their thing; and in case there has no consent choice been made yet (i.e. the cookie banner is presented to the visitor), they'll also be called as soon as the visitor saves their choices, so it will start tracking immediately, and not just after the next page view.

Feel free to use and/or refine this - I'm no developer, so please forgive my rather messy approach here. 🙂

NicoRi
Excursionist
15 0 4

Update: The thirdPartyMarketingAllowed() method is now called marketingAllowed(), so this is aforementioned code with the proper methods provided by the API, properly working as of the time of this post:

<script>
    function msClarity() {
          let userCanBeTracked = window.Shopify.customerPrivacy.analyticsProcessingAllowed();
          if(userCanBeTracked) {
            (function(c,l,a,r,i,t,y){
              c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
              t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
              y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
            })(window, document, "clarity", "script", "[REDACTED]");
          }
    }

    function bingConv() {
      let userCanBeTracked = window.Shopify.customerPrivacy.marketingAllowed();
      if(userCanBeTracked) {
        (function(w,d,t,r,u) {
          var f,n,i;w[u]=w[u]||[],f=function(){var o={ti:"[REDACTED]", enableAutoSpaTracking: true};
          o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")
          },
          n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function()
          {
            var s=this.readyState;
            s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)
          },
          i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)
        })
        (window,document,"script","//bat.bing.com/bat.js","uetq");
      }
    }

    window.Shopify.loadFeatures([
          {
            name: 'consent-tracking-api',
            version: '0.1',
          }
          ],
          function(error) {
            if (error) {
              throw error;
            }
            msClarity();
            bingConv();
            document.addEventListener('visitorConsentCollected', () => {
              msClarity();
              bingConv();
            });
    });
</script>