Cloudflare Zaraz - Tool Triggering based on Cookie Consent
I’ve previous been using Google Tag Manager (GTM) for additional content; Google Analytics, Google AdSense, Facebook Pixel, etc.. on another website. All additional content is, of course, controlled by cookie consent (in my case, using OneTrust) and set / agreed to by the user when they visit the site.
The following notes detail the initial stages of moving the work of the GTM ‘container’ over to the Cloudflare’s Zaraz service, which works in a similar way to GTM but provides site speed and security benefits as the work happens in the cloud rather than on the user’s / client device.
Development setup
My journey involved a little trial and error as it’s still early days for the service and its documentation. However, I found the use of the ‘Zaraz HTTP Request’ tool to be a major help as it allows an HTTP Request to be triggered and thus (if you have a way to monitor that request’s endpoint) provide confidence that your ideas are working (or not!). I made a previous post about it, so if you’ve not read it, check out Cloudflare Zaraz - Using the HTTP Request Tool for Trigger setup / debug. The big takeaway from that was the ability to contain results (good or bad) to my development site, which I’m able to run up on a sub domain away from the production version! You’ll see that nugget throughout this post referenced as a ’trigger’ named NOT _dev
which appears in the ‘Blocking Triggers’ of all my development work i.e. the trigger will be BLOCKED
if the calling page doesn’t belong to my dev site. The instructions to create it are detailed in the other post so I’ll not repeat that here. Just thought I’d mention why it’s there - of course, once we’re finished with dev it’s simply a case of removing those NOT _dev
blocks to allow use in prod 🤓.
Triggers (Rules)
In order to get the ball rolling, we first need a way to ’trigger’ Zaraz’s ’tools’; the tools will be setup once the triggers are in place.
Task #1 - supply the cookie control code. I don’t currently include this in the regular site code as I use one of two versions (as you’ll see, below). In order to know which version of the code to add to the page, I check if the user has visited the site before. If they have, then the cookies recording their previous cookie consent will be available (and used). If they’re a new visitor, we need them to consent to / choose cookies etc. Rather than code that logic, I’m letting Zaraz handle it 🤓
At this point I came across a …
.+
is NOT enough to match for a non-empty string (for some reason 🤯). Use .{2,}
to successfully match for a non-empty string, i.e. there appears to be an extra character included somewhere before the regex code gets to see it 🤔.… so, that’s why .{2,}
is used below to check for a non-empty value!
Anyway, on with the setup.
In the case of OneTrust, it creates two cookies that are, of course, ‘always allowed’ as they are directly responsible for the site’s function:
OptanonConsent
: which initially contains the default cookie group choices.OptanonAlertBoxClosed
: which simply contains a timestamp once the user closes the alert box after confirming their cookie choices.
The OneTrust code then emits a few different events that are available to be used as hooks. The one I use to replace the regular Pageview
event is OneTrustLoaded
as that now ensures we have our cookie control, well, loaded.
Task #2 - based on the cookie control code and the groups it provides for types of cookies, plus the events fired … we can ALLOW/BLOCK
tools being triggered if they are dependant on a cookie group setting. The following triggers provide that control.
OneTrust ‘Triggers’ (rules)
- Name:
Cookie - IS NOT PRESENT - OptanonConsent
- Match rule
{{ system.cookies.OptanonConsent }}
Not matches regex.{2,}
- Match rule
Name:
Cookie - IS NOT PRESENT - OptanonAlertBoxClosed
- Match rule
{{ system.cookies.OptanonAlertBoxClosed }}
Not matches regex.*\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*
- Match rule
Name:
Optanon Cookies PRESENT
- Match rule
{{ system.cookies.OptanonConsent }}
Matches regex.{2,}
- AND
- Match rule
{{ system.cookies.OptanonAlertBoxClosed }}
Matches regex.*\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*
- Match rule
Name:
C0001 Disabled
- Match rule
{{ client.OnetrustActiveGroups }}
Not matches regex.*C0001.*
- Match rule
Name:
C0002 Disabled
- Match rule
{{ client.OnetrustActiveGroups }}
Not matches regex.*C0002.*
- Match rule
Name:
C0003 Disabled
- Match rule
{{ client.OnetrustActiveGroups }}
Not matches regex.*C0003.*
- Match rule
Name:
C0004 Disabled
- Match rule
{{ client.OnetrustActiveGroups }}
Not matches regex.*C0004.*
- Match rule
Name:
C0005 Disabled
- Match rule
{{ client.OnetrustActiveGroups }}
Not matches regex.*C0005.*
- Match rule
Name:
OneTrustLoaded
- Match rule
{{ client.__zarazTrack }}
EqualsOneTrustLoaded
- Match rule
Tools
Under control of our triggers we’re now able to hook up some tools. Cloudflare Zaraz has a bunch of preset tools but before setting those up I’ve created a set of custom tools - all HTTP Requests - to provide confidence that the trigger conditions work. You can see the conditions that fire or block (allow or deny) the triggering of tools in the details below.
Initially though, I’ve implemented those two versions of the OneTrust initialisation code.
Custom HTML - Cookie Consent Init
This will supply the code for the first invocation of the Cookie Consent, i.e. for new visitors to the site. It should only trigger if either the OptanonConsent
and/or OptanonAlertBoxClosed
cookies are missing i.e. It’s BLOCKED
if they are both present. The code here is differentiated in case we want to do something on the initial Cookie Consent setup. Here, it’s simply adding a pleasant “1 second delay” before the user is shown the inevitable cookie consent overlay.
Tool:
Custom HTML
Action:
Name:
Cookie Consent Init
Firing Triggers:
Pageview
Blocking Triggers:
NOT _dev
Optanon Cookies PRESENT
HTML Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<script> (function() { try { window.setTimeout( function(){ var el = document.createElement('script'); el.setAttribute('async', ''); el.setAttribute('src', '/plugins/oneTrust/scripttemplates/otSDKStub.js'); el.setAttribute('data-domain-script', '4fa46b09-a14e-4a11-2e6f-1e4e58d9afd4'); document.body.appendChild(el); // console.log("Cookie Consent Init"); }, 1000 ); } catch (err) { // console.log(err); } })(); </script> <script> function OptanonWrapper() {} </script>
Custom HTML - Cookie Consent
This will supply the code for the regular invocation of the Cookie Consent. We need this version to trigger if the init version has previously succeeded in generating both the required cookies. It’s BLOCKED
if either of the cookies are missing - and the init version can then do its thing instead.
Tool:
Custom HTML
Action:
Name:
Cookie Consent
Firing Triggers:
Pageview
Blocking Triggers:
NOT _dev
Cookie - IS NOT PRESENT - OptanonConsent
Cookie - IS NOT PRESENT - OptanonAlertBoxClosed
HTML Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
<script> (function() { var el = document.createElement('script'); el.setAttribute('async', ''); el.setAttribute('src', '/plugins/oneTrust/scripttemplates/otSDKStub.js'); el.setAttribute('data-domain-script', '4fa46b09-a14e-4a11-2e6f-1e4e58d9afd4'); document.body.appendChild(el); // console.log("Cookie Consent"); })(); </script> <script> function OptanonWrapper() {} </script>
HTTP Request - Test Trigger C0001 Enabled
We’ll use this and the following “Test Triggers” simply to verify our triggering logic for content that’s allowed by the C0001
cookie group (i.e. Essential / Strictly necessary cookies)
Tool:
HTTP Request
Action:
- Name:
Test Trigger C0001 Enabled
- Firing Triggers:
OneTrustLoaded
- Blocking Triggers:
NOT _dev
C0001 Disabled
- Endpoint: use a suitable test endpoint (I’m using pipedream.com here), for example:
https://eoe166w3tkn8wqv.m.pipedream.net/C0001-Trigger
- HTTP Method:
POST JSON
- Send all System and Client data:
Enable
- Name:
So, the only time this endpoint will get a hit is (in this example)
- A
OneTrustLoaded
event is received (i.e. a page is viewed) - AND
- NONE of the following conditions are true
- The page does not belong to our dev site
- The
C0001
OnetrustActive group has not been set / agreed to (i.e. it’s disabled)
Please excuse the double negatives, but the Cloudflare Zaraz config doesn’t currently make that easy 🙄. That may change as at the time of writing it’s still in beta 🤓
HTTP Request - Test Trigger C0002 Enabled
Tool:
HTTP Request
Action:
- Name:
Test Trigger C0002 Enabled
- Firing Triggers:
OneTrustLoaded
- Blocking Triggers:
NOT _dev
C0002 Disabled
- Endpoint: use a suitable test endpoint, for example:
https://eoe166w3tkn8wqv.m.pipedream.net/C0002-Trigger
- HTTP Method:
POST JSON
- Send all System and Client data:
Enable
- Name:
HTTP Request - Test Trigger C0003 Enabled
Tool:
HTTP Request
Action:
- Name:
Test Trigger C0003 Enabled
- Firing Triggers:
OneTrustLoaded
- Blocking Triggers:
NOT _dev
C0003 Disabled
- Endpoint: use a suitable test endpoint, for example:
https://eoe166w3tkn8wqv.m.pipedream.net/C0003-Trigger
- HTTP Method:
POST JSON
- Send all System and Client data:
Enable
- Name:
HTTP Request - Test Trigger C0004 Enabled
Tool:
HTTP Request
Action:
- Name:
Test Trigger C0004 Enabled
- Firing Triggers:
OneTrustLoaded
- Blocking Triggers:
NOT _dev
C0004 Disabled
- Endpoint: use a suitable test endpoint, for example:
https://eoe166w3tkn8wqv.m.pipedream.net/C0004-Trigger
- HTTP Method:
POST JSON
- Send all System and Client data:
Enable
- Name:
Usage
Based on the above settings we can now watch our HTTP Request endpoints and see them hit or not depending on the cookie settings we set for our site’s page requests.
Once we’re happy with the test HTTP Request triggers, we can port those same firing / blocking conditions to ‘real’ tools, such as GA4, Google AdSense, various pixels, etc, and be confident that they’re only being instantiated IF the client has allowed them 😎
Annex
Cookie Groups
C0001
Strictly necessary cookies (Essential - allow the website to work)C0002
Statistics cookies (Performance - how the website is used / third-party analytics)C0003
Preferences cookies (Functional - simply store your site preferences)C0004
Marketing cookies (Targeting - track your activity online / third-party)