Where the law needs a visitor's consent before a referral cookie is stored, Bolt Claw's website tag waits for your consent banner: one attribute on the tag, one call from the banner. Below are a short helper, a snippet for each common consent tool, and a paragraph for your own cookie policy.
This page explains what the tag does. It is not legal advice: whether you need consent, and for which visitors, is for you and your adviser to decide.
When you need it
- The EU. Storing anything on a visitor's device, or reading it from there, needs their consent unless it is strictly necessary for a service they asked for (Article 5(3) of the ePrivacy Directive). France's CNIL says in question 13 of its cookie FAQ that trackers used to bill affiliate operations are not exempt.
- The UK. The ICO takes the same position on affiliate click and conversion tracking, under regulation 6 of PECR.
- One possible exception. The CNIL's question 14 accepts that trackers needed for a cashback or reward scheme the visitor joined may be exempt. That is about a reward the visitor asked for, not a partner's commission; take advice before you rely on it.
- Elsewhere, other laws may ask for a notice or an opt-out instead.
On the program's Integration tab, Edit answers, turn on Our audience
includes the EU or the UK. The tags the Integration and Welcome tabs then give you
carry data-consent="required", and the setup status warns you if the tag it sees
on your site does not wait for consent.
What the tag stores
Everything is first-party, on your own domain. The tag sets nothing on
boltclaw.ai, creates no visitor id and reads only what it wrote.
| Name | Kind | Holds | For |
|---|---|---|---|
bc_ref |
Cookie, and a localStorage copy |
The partner's referral code | The program's cookie window |
bc_click |
Cookie, and a localStorage copy |
The click id from the link (16 random letters and digits) | The cookie window |
bc_sub |
Cookie, and a localStorage copy |
The partner's campaign tag, when the link has one | The cookie window |
bc_welcome_dismissed:<code> |
localStorage |
1, once the visitor closes the welcome |
Until the visitor clears it |
The cookie window is the program's Cookie window (days) on its Settings tab, 1
to 365 and 30 unless you changed it. Each cookie is Path=/, SameSite=Lax and,
on https, Secure. The copy is there because some in-app browsers drop cookies
between pages; an expired copy is deleted when the tag next reads it.
Consent mode
Add one attribute to the tag:
<script src="https://boltclaw.ai/referrals/v2.js" defer
data-consent="required"></script>
Before the visitor answers, the tag reads the code, click id and campaign tag
from the address and keeps them in the page's memory only. It stores nothing,
reads nothing it stored before, makes no request, leaves Stripe Payment Links alone,
draws no welcome, and BoltClawReferral.offer() waits. code(), clickId(),
sub(), clientReferenceId() and attach(form) still give that page's values, so
a form sent from the landing page can carry them; if you would rather not, call
them only after consent.
BoltClawReferral.consent(true) when the visitor accepts: the tag stores what
the page read (by the program's first-click or last-click rule), reads what it
stored after an earlier consent, and turns on the welcome, the offer and Payment
Links if you use them.
BoltClawReferral.consent(false) when the visitor refuses or withdraws: the
tag forgets what the page read and neither reads nor writes storage on that page
unless they accept later. It does not delete what it stored on an earlier page;
the helper below does.
Four rules:
- Tell the tag on every page. It does not remember the answer between pages; your consent tool does. Every snippet below reads the saved answer as each page loads.
- Never call
consent(false)before the visitor answers. It forgets the code, and a laterconsent(true)on the same page has nothing left to store. While they have not answered, call nothing. - Never define
window.BoltClawReferralyourself, not even as a stub: the tag finds it there and does not start. - Calls are safe to repeat, and without
data-consent="required"the tag ignores them. Version 1 (v1.js) has no consent mode; usev2.js.
The helper
Put this right after the tag, in the <head>, before your consent tool's own
script where you can. It is the same for every tool: it passes the answer to the
tag even when your consent tool answers before the tag has loaded, and on a
refusal or withdrawal it deletes what the tag stored.
<script src="https://boltclaw.ai/referrals/v2.js" defer
data-consent="required"></script>
<script>
(function () {
var NAMES = ["bc_ref", "bc_click", "bc_sub"];
var answer = null;
function tell() {
if (answer !== null && window.BoltClawReferral) window.BoltClawReferral.consent(answer);
}
function forget() {
NAMES.forEach(function (name) {
document.cookie = name + "=; Path=/; Max-Age=0; SameSite=Lax";
});
try {
for (var i = localStorage.length - 1; i >= 0; i--) {
var key = localStorage.key(i) || "";
if (NAMES.indexOf(key) !== -1 || key.indexOf("bc_welcome_dismissed:") === 0) {
localStorage.removeItem(key);
}
}
} catch (e) {}
}
// true: the visitor accepted. false: they refused or withdrew. Only once they answer.
window.boltclawConsent = function (granted) {
answer = granted === true;
tell();
if (!answer) forget();
};
document.addEventListener("DOMContentLoaded", tell);
window.addEventListener("load", tell);
})();
</script>
Then add your tool's snippet below it. Each one names the category to put the tag
in: list bc_ref, bc_click and bc_sub there in your tool's cookie list, by
hand if its scan does not find them (a scan sees them only on a page opened from a
referral link).
Cookiebot
Category: Marketing.
<script>
function boltclawFromCookiebot() {
if (!window.Cookiebot || !Cookiebot.consent) return;
if (Cookiebot.consent.marketing) boltclawConsent(true);
else if (Cookiebot.consented || Cookiebot.declined) boltclawConsent(false);
}
window.addEventListener("CookiebotOnConsentReady", boltclawFromCookiebot);
document.addEventListener("DOMContentLoaded", boltclawFromCookiebot);
</script>
CookiebotOnConsentReady fires when the answer is loaded from an earlier visit and
whenever the visitor submits one; Cookiebot.consented or Cookiebot.declined is
true only once they have answered.
OneTrust
Category: Targeting Cookies, group C0004 in OneTrust's default set. If you
put the tag in a group of your own, use its id instead.
<script>
function boltclawFromOneTrust(groups) {
if (("," + groups + ",").indexOf(",C0004,") !== -1) boltclawConsent(true);
else if (window.OneTrust && typeof OneTrust.IsAlertBoxClosed === "function" && OneTrust.IsAlertBoxClosed()) {
boltclawConsent(false);
}
}
window.addEventListener("OneTrustGroupsUpdated", function (event) {
boltclawFromOneTrust((event.detail || []).join(","));
});
document.addEventListener("DOMContentLoaded", function () {
if (typeof window.OnetrustActiveGroups === "string") boltclawFromOneTrust(OnetrustActiveGroups);
});
</script>
OneTrustGroupsUpdated fires as OneTrust loads and whenever the visitor changes
their choice, with the active group ids; OneTrust.IsAlertBoxClosed() is true once
they have answered.
Usercentrics
Category: Marketing. In the Usercentrics admin, add Bolt Claw as a custom
service in the Marketing category, named exactly Bolt Claw Referrals, with the
three cookies. This uses the Web CMP v3 event UC_CONSENT, which fires as the page
loads (with the saved answer) and after every change.
<script>
window.addEventListener("UC_CONSENT", function (event) {
var detail = event.detail || {};
var services = detail.services || {};
for (var id in services) {
if (services[id].name !== "Bolt Claw Referrals") continue;
if (services[id].consent && services[id].consent.given) boltclawConsent(true);
else if (detail.consent && detail.consent.type === "EXPLICIT") boltclawConsent(false);
}
});
</script>
A consent of type EXPLICIT is one the visitor gave; before that, the service's
default is not an answer, so nothing is called.
CookieYes
Category: Advertisement (advertisement; CookieYes's events use the original
category ids even if you renamed the category).
<script>
function boltclawFromCookieYes(consent) {
if (consent.categories && consent.categories.advertisement) boltclawConsent(true);
else if (consent.isUserActionCompleted) boltclawConsent(false);
}
document.addEventListener("cookieyes_banner_load", function (event) {
boltclawFromCookieYes(event.detail || {});
});
document.addEventListener("cookieyes_consent_update", function (event) {
var accepted = (event.detail && event.detail.accepted) || [];
boltclawFromCookieYes({
categories: { advertisement: accepted.indexOf("advertisement") !== -1 },
isUserActionCompleted: true,
});
});
document.addEventListener("DOMContentLoaded", function () {
if (typeof window.getCkyConsent === "function") boltclawFromCookieYes(getCkyConsent() || {});
});
</script>
cookieyes_banner_load carries the saved answer as the banner loads (and
getCkyConsent() returns it once the banner has loaded), and
cookieyes_consent_update each new one. CookieYes's WordPress plugin sends these
events only when it is connected to the CookieYes web app; on WordPress you can use
the WP Consent API instead (below).
Klaro
Purpose: marketing, as in Klaro's own example configuration (add a translation
for it if your configuration has none). Add this service to the services list in
your Klaro configuration, and load the helper above before Klaro's own script,
because Klaro calls the service's callback as soon as it starts:
{
name: "boltclaw-referrals",
title: "Bolt Claw referrals",
purposes: ["marketing"],
cookies: ["bc_ref", "bc_click", "bc_sub"],
callback: function (consent, service) {
if (consent) boltclawConsent(true);
else if (service.boltclawAccepted) boltclawConsent(false);
service.boltclawAccepted = consent;
},
},
Klaro calls callback with false before the visitor has answered as well as
after a refusal, so this passes on a "no" only after an earlier "yes"; until then
the tag keeps waiting, which stores nothing. Klaro deletes the listed cookies itself
when consent is withdrawn.
Shopify
With Bolt Claw's Shopify app there is nothing to add: switch on the app embed, and keep Wait for the visitor's consent on (the default). It passes the visitor's marketing choice from Shopify's own cookie banner to the tag. See Referrals for Shopify.
Without the app (the tag in your theme yourself), use Shopify's Customer
Privacy API. Category: marketing (marketingAllowed: marketing, attribution
and targeted advertising). In theme.liquid, put the tag, the helper and this
after {{ content_for_header }}.
<script>
function boltclawFromShopify() {
var privacy = window.Shopify && window.Shopify.customerPrivacy;
if (!privacy) return;
if (privacy.marketingAllowed()) boltclawConsent(true);
else if (privacy.currentVisitorConsent().marketing === "no") boltclawConsent(false);
}
document.addEventListener("visitorConsentCollected", boltclawFromShopify);
if (window.Shopify && window.Shopify.loadFeatures) {
window.Shopify.loadFeatures([{ name: "consent-tracking-api", version: "0.2" }], function (error) {
if (!error) boltclawFromShopify();
});
}
</script>
currentVisitorConsent().marketing is "yes", "no", or "" while the visitor
has not answered.
WordPress: the WP Consent API
With Bolt Claw's WooCommerce plugin there is nothing to add: when a consent plugin that supports the WP Consent API is active, the plugin turns consent mode on, registers the three cookies under marketing, and passes the answer to the tag. See Referrals for WooCommerce.
Without it, with the tag in your theme and a consent plugin that supports the WP Consent API: category marketing.
<script>
function boltclawFromWordPress() {
if (typeof window.wp_has_consent === "function" && wp_has_consent("marketing")) {
boltclawConsent(true);
}
}
document.addEventListener("wp_consent_type_defined", boltclawFromWordPress);
document.addEventListener("DOMContentLoaded", boltclawFromWordPress);
document.addEventListener("wp_listen_for_consent_change", function (event) {
var changed = event.detail || {};
if (changed.marketing === "allow") boltclawConsent(true);
else if (changed.marketing === "deny") boltclawConsent(false);
});
</script>
Your own banner, or another tool
Call boltclawConsent(true) when the visitor accepts the category you put the tag
in, and boltclawConsent(false) when they refuse it or withdraw. For a visitor who
answered on an earlier visit, call it with their saved answer as each page loads.
While they have not answered, call nothing.
Check it
- Open your site in a private window with
?via=and one of your partners' codes. - Before you answer the banner, your browser's developer tools (Application,
Cookies) show no
bc_ref. - Accept:
bc_refappears, for the program's cookie window. Open another page: it is still there, andBoltClawReferral.code()in the console returns the code. - Withdraw consent in your tool:
bc_ref,bc_clickandbc_subare gone.
The Integration tab's setup status also says whether the tag it sees waits for consent. For a tag added by a tag manager, open your site with the setup status's verify link.
A paragraph for your cookie policy
Paste this into your own cookie policy, replacing {{cookieDays}} with the
program's cookie window. Adapt it as you need; your policy stays yours.
Referral cookies. If you arrive on our website through a link from one of our referral partners, we use Bolt Claw's referral tag to remember which partner sent you, so that we can reward them if you sign up or buy and check that the referral is genuine. It stores the partner's referral code, a random number for that click and, if the partner added one, the name of their campaign, in cookies named
bc_ref,bc_clickandbc_subon our own website, with a copy of each in your browser's local storage, for {{cookieDays}} days. If you close the welcome message the tag can show, it also remembers that in local storage. Bolt Claw sets no cookie of its own, and these cookies hold no name or email address. Where the law requires it, we store them only after you agree to marketing cookies, and you can change your choice at any time in our cookie settings.