Cookie Consent and GDPR Compliance for the Velaro Chat Widget
> Disclaimer: This article describes how the Velaro chat widget handles data and provides configuration options for common compliance scenarios. It is not legal advice. Requirements under GDPR, CCPA, ePrivacy, and other regulations vary by jurisdiction, industry, and specific implementation. Please consult your legal counsel to determine the appropriate configuration for your organization.
Overview
The Velaro chat widget can be configured to support cookie consent and privacy compliance requirements on your website. This article explains exactly what data the widget collects, when it collects it, and how to control that behavior.
> This article covers the Velaro Chat widget (v10). For the Velaro Messenger platform (the new Velaro), see Velaro Messenger — Automatic Consent Detection at the bottom — consent is fully automatic with one line of configuration, no developer wiring required.
What the Widget Collects by Default
When the Velaro widget loads using the standard embed code, the following occur immediately on page load, before any visitor interaction:
| Data | Where Stored | What It Contains |
|---|---|---|
| velaro_hitCount | Browser localStorage | Running count of pages visited across sessions |
| velaro_viewedPages | Browser localStorage | Array of the last 10 URLs the visitor has viewed |
| velaro_pageHits | Browser localStorage | Array of the last 20 page URLs with timestamps |
| Visitor registration | Velaro servers | Referrer URL, UTM parameters, current page URL, page history, Google Analytics ID, HubSpot cookie ID |
Under GDPR's ePrivacy rules, localStorage is treated identically to cookies. These items contain behavioral tracking data and are generally classified as functional rather than strictly necessary, meaning they may require consent before being set on sites subject to opt-in cookie consent laws.
Quick Decision Guide
| What you want | What to do |
|---|---|
| Chat button visible to all visitors, including those who accept only Strictly Necessary cookies. Nothing stored, nothing sent to Velaro until the visitor clicks. Recommended for strict DPOs and EU/German compliance (ePrivacy, §25 TDDDG). | Option 2: deferLoadUntilInteraction |
| Chat bubble shows for all visitors. No cookies or localStorage before click. Clicking the bubble is the consent signal. Simplest setup. | Option 1: deferStorageUntilInteraction |
| Chat bubble shows for all visitors. Tracking respects what the visitor chose in your cookie banner. No tracking if they rejected, full tracking if they accepted. | Option 3: privacyConsent wired to your banner |
| Strictest: No tracking before interaction AND no tracking even on click if they rejected cookies. | Option 4: Options 1 and 3 combined |
| I use Google Tag Manager and the chat bubble disappears for visitors who only accept Strictly Necessary cookies. | Read the GTM section below — this is a GTM trigger or OtAutoBlock misconfiguration, not a Velaro setting. |
| I use Velaro Messenger (the new platform) and want automatic consent detection. | See the Velaro Messenger section below — one line of config, no wiring needed. |
| No cookie consent requirement on your site. | No change needed. |
---
Option 2: Click-to-Load — Button Visible to All Visitors (deferLoadUntilInteraction)
The deferLoadUntilInteraction option shows a branded chat button immediately to every visitor, including those who accept only Strictly Necessary cookies, with nothing stored on the visitor's device and no visitor data sent to Velaro's servers until the visitor clicks. This is the recommended option for customers with strict GDPR requirements or DPO review.
What happens on page load
| Action | Standard | With deferLoadUntilInteraction |
|---|---|---|
| Chat button visible to all visitors | Yes | Yes — always, regardless of cookie choice |
| Shows live agent availability | Yes | Yes |
| Cookies written | Yes | No |
| localStorage written | Yes | No |
| Visitor registration (API call) | Yes | No — deferred until click |
| Button configuration fetch (appearance) | Yes | Yes — read-only, no visitor data |
| Agent availability check | Yes | Yes — read-only, no visitor data |
| Proactive invites | Yes | No |
Network calls on page load
Three lightweight read-only requests go to Velaro's servers on page load: two fetch your chat button configuration (your brand colors, button icon, messaging) and one checks whether agents are currently online. These requests carry only your site ID — no visitor identifier, no cookie, no tracking data of any kind. The first request that carries any visitor information goes out only when a visitor clicks the button to open chat.
Legal basis
The button is visible on screen but data-dormant. Nothing is stored on or read from the visitor's device until they click. Under ePrivacy Art. 5(3) and §25 TDDDG, the trigger for consent is storage of or access to information on a device — which does not occur until the visitor's click. The click itself is the explicit, user-initiated action that satisfies the regulation. This approach is used by major live chat providers worldwide for EU-compliant deployments and has been validated by German, Dutch, and French DPA guidance.
How to enable
Velaro('boot', {
siteId: YOUR_SITE_ID,
deferLoadUntilInteraction: true
});
That is the only change required to the embed code. Do not also include deferStorageUntilInteraction: true — they address the same concern and combining them is redundant.
What visitors experience
Before clicking the button: The branded chat button appears and shows whether agents are available. Nothing is written to the visitor's browser. No visitor data is sent to any server.
After clicking the button: The full chat experience begins — routing, agent assignment, visit history, pre-chat forms, everything works exactly as it does today. The only difference is when the session starts, not how it works.
Important: proactive invites
Proactive invites — timed pop-ups, exit-intent messages, or rule-based prompts — do not work with this option because they depend on page visit data that loads at boot. If proactive invites matter to your workflow, use Option 3 (privacyConsent wired to your banner) so tracking loads the moment a visitor accepts cookies.
OneTrust users — required OneTrust configuration
For deferLoadUntilInteraction to work for visitors who accept only Strictly Necessary cookies, the Velaro shim must be classified correctly in OneTrust Auto-Blocking:
eastprodcdn.azureedge.net/widgets/shim → Strictly Necessary (C0001)
The shim with deferLoadUntilInteraction writes nothing to the visitor's device and collects no visitor data on page load. Strictly Necessary is the correct and legally defensible classification. If it remains as Functional (C0003), OneTrust's OtAutoBlock will prevent the shim from loading for Strictly Necessary-only visitors — the button will never appear for them, defeating the purpose of this option.
Also verify these Azure session cookies are classified correctly in your OneTrust cookie declaration:
| Cookie | Host | OneTrust Category |
|---|---|---|
ARRAffinity | api-visitor-us-east.velaro.com | Strictly Necessary — C0001 |
ARRAffinitySameSite | api-visitor-us-east.velaro.com | Strictly Necessary — C0001 |
These are Azure infrastructure cookies that keep a visitor on a consistent server. They contain no personal data, are session-only, and set only when a visitor initiates a chat. Strictly Necessary is their correct classification.
> Do not use data-ot-ignore as an alternative to the category change. When OtAutoBlock is told to skip a script via data-ot-ignore, it also skips its internal allow-list step — the widget's iframe then cannot communicate with the parent page and the widget fails silently, with no bubble and no network calls, even for visitors who accepted Functional cookies. The category change to C0001 is the only reliable fix.
---
Option 1: Defer Storage Until Interaction (deferStorageUntilInteraction)
The deferStorageUntilInteraction option causes the widget to wait until a visitor actively clicks the chat bubble before writing any data to the visitor's browser. The full widget loads on page load (including a visitor API call), but localStorage writes are deferred until interaction.
What changes
| Behavior | Standard | With deferStorageUntilInteraction |
|---|---|---|
| Chat bubble appears on page | Yes | Yes |
| Shows agent availability in real time | Yes | Yes |
| localStorage written on page load | Yes | No |
| Visitor API called on page load | Yes | Yes |
| Full chat experience when visitor opens chat | Yes | Yes — no change |
| Proactive chat invites | Yes | No |
How to enable
Velaro('boot', {
siteId: YOUR_SITE_ID,
deferStorageUntilInteraction: true
});
Important: visitors who reject cookies
With this option alone, the widget does not know about your cookie banner. A visitor who clicks "Reject All" and then clicks the chat bubble will still be tracked when they open chat — the widget treats clicking the bubble as an intentional action. If you need to fully honor rejections, combine this option with Option 3.
If your goal is that nothing is sent to Velaro's servers until a visitor clicks, use Option 2 (deferLoadUntilInteraction) instead.
---
Option 3: Wire to Your Cookie Consent Banner (privacyConsent)
The privacyConsent option connects the widget directly to your existing cookie consent banner. Your developer calls a provided callback with true when the visitor accepts and false when they reject. The widget then behaves accordingly in real time — no page reload required.
What changes based on visitor choice
When visitor accepts cookies — done(true):
- Cookies enabled immediately in the current session
- Visitor tracking loads immediately — no page reload required
- Proactive invites become eligible from that point forward
- Full inline chat experience
When visitor rejects cookies — done(false):
- No localStorage written, no visitor API call, even if they click the chat bubble
- Clicking the bubble opens a popout window rather than expanding inline
- The visitor can still chat — the experience is functional but slightly different
- If they later change their mind and accept, tracking loads immediately without a page reload
How to enable (generic pattern)
Velaro('boot', {
siteId: YOUR_SITE_ID,
privacyConsent: function(done) {
// Call done(true) when the visitor accepts cookies
// Call done(false) when the visitor rejects cookies
// This callback fires on initial decision AND when the visitor changes their mind
done(visitorHasAcceptedFunctionalCookies);
}
});
Common platform examples
OneTrust:
Velaro('boot', {
siteId: YOUR_SITE_ID,
privacyConsent: function(done) {
function check() {
// C0003 is the Functional category in most OneTrust configurations
var groups = window.OnetrustActiveGroups || '';
done(groups.indexOf('C0003') !== -1);
}
if (window.OneTrust && window.OneTrust.IsAlertBoxClosed()) {
check();
} else {
window.addEventListener('OTConsentApplied', check);
}
// Re-fire when visitor changes preferences
window.addEventListener('OTConsentApplied', check);
}
});
Cookiebot:
Velaro('boot', {
siteId: YOUR_SITE_ID,
privacyConsent: function(done) {
function check() {
done(!!(window.Cookiebot &&
window.Cookiebot.consent &&
window.Cookiebot.consent.preferences));
}
if (window.Cookiebot && window.Cookiebot.loaded) {
check();
} else {
window.addEventListener('CookiebotOnLoad', check);
}
window.addEventListener('CookiebotOnConsentReady', check);
}
});
Custom or in-house banner:
Velaro('boot', {
siteId: YOUR_SITE_ID,
privacyConsent: function(done) {
// Store the callback so your banner code can call it
window._velaroDone = done;
}
});
// Then in your banner's accept handler, add:
// window._velaroDone && window._velaroDone(true);
// And in your banner's reject handler, add:
// window._velaroDone && window._velaroDone(false);
---
Option 4: Combine Options 1 and 3
For the strictest compliance posture — nothing written before interaction AND full respect for the visitor's banner decision — use both deferStorageUntilInteraction and privacyConsent together:
Velaro('boot', {
siteId: YOUR_SITE_ID,
deferStorageUntilInteraction: true,
privacyConsent: function(done) {
// wire to your banner
done(visitorHasAcceptedFunctionalCookies);
}
});
With both options active:
| Scenario | Result |
|---|---|
| Visitor has not interacted with banner yet, has not clicked chat | Nothing written. Bubble visible. |
| Visitor accepts cookies | Tracking loads immediately in the current session. Proactive invites eligible. |
| Visitor rejects cookies and clicks the bubble | Nothing tracked. Popout window opens. Chat works. |
| Visitor rejects, later changes to accept | Tracking loads immediately. No page reload needed. |
---
Google Tag Manager (GTM) Users — Important
If your site loads Velaro through Google Tag Manager, there are two separate issues that can cause the chat bubble to disappear for visitors who accept only Strictly Necessary cookies. This section explains both.
Issue 1 — GTM consent trigger blocking the boot command
GTM lets you attach consent conditions to each tag — for example, "only fire this tag if the visitor accepted Functional cookies (OneTrust category C0003)." Many developers put this condition on the Velaro tag, intending to protect privacy. The result is that when a visitor accepts Strictly Necessary only, GTM loads successfully but the Velaro boot command never runs, and the chat bubble never appears.
What to change in GTM:
- Open your GTM container
- Find the tag that contains
Velaro('boot', ...)— often named "Velaro Chat" or "Live Chat" - Go to Triggering
- Remove any consent condition that requires Functional cookies (OneTrust C0003 or equivalent) before the tag fires
- Set the trigger to fire on All Pages for all visitors, regardless of consent choice
- Add
deferLoadUntilInteraction: trueto your boot command (see Option 2 above) — this handles consent at the widget level - Publish and test
What your GTM Velaro tag should contain:
Velaro('boot', {
siteId: YOUR_SITE_ID,
groupId: YOUR_GROUP_ID,
deferLoadUntilInteraction: true
});
If you also want to fully honor rejections (no tracking even on click for visitors who rejected):
Velaro('boot', {
siteId: YOUR_SITE_ID,
groupId: YOUR_GROUP_ID,
deferStorageUntilInteraction: true,
privacyConsent: function(done) {
function check() {
done((window.OnetrustActiveGroups || '').indexOf('C0003') !== -1);
}
if (window.OneTrust && window.OneTrust.IsAlertBoxClosed()) { check(); }
else { window.addEventListener('OTConsentApplied', check); }
window.addEventListener('OTConsentApplied', check);
}
});
Issue 2 — OneTrust OtAutoBlock intercepting the shim script
Even with the GTM trigger fixed, if you use OneTrust's OtAutoBlock feature, it may intercept the Velaro CDN file before it can load. OtAutoBlock reads each script tag's src URL and checks whether that URL is categorized as Functional (C0003) or Strictly Necessary (C0001). If the Velaro CDN URL is categorized as C0003, OtAutoBlock blocks it for visitors who accepted Strictly Necessary only — and the chat button never appears.
How to check: In your OneTrust account, go to Cookies → Auto-Blocking and look for eastprodcdn.azureedge.net. If it is assigned to the Functional category (C0003), that is the cause.
The fix — change the category to Strictly Necessary (C0001):
Change the category for eastprodcdn.azureedge.net/widgets/shim from Functional (C0003) to Strictly Necessary (C0001). When the widget is configured with deferLoadUntilInteraction: true, the shim script sets no cookies, writes nothing to the browser, and collects no visitor data. It is a loader that shows a button and checks agent availability. Strictly Necessary is the correct classification.
Also set these Azure session cookies to Strictly Necessary (C0001) in your OneTrust cookie declaration:
| Cookie | Host | Category |
|---|---|---|
ARRAffinity | api-visitor-us-east.velaro.com | Strictly Necessary — C0001 |
ARRAffinitySameSite | api-visitor-us-east.velaro.com | Strictly Necessary — C0001 |
These are Azure infrastructure cookies that keep the visitor on a consistent server. They contain no personal data, are session-only, and only set when a visitor initiates a chat session. Their correct classification is Strictly Necessary.
> Do not use data-ot-ignore to work around OtAutoBlock. When OtAutoBlock bypasses a script via data-ot-ignore, it also skips its internal allow-list step, which prevents the widget's iframe from communicating with the parent page. The widget fails silently — no bubble, no network calls, even for visitors with Functional consent accepted. The category change to C0001 is the reliable fix.
Why this is compliant
The chat button with deferLoadUntilInteraction writes nothing to any visitor's device. The compliance control is the deferLoadUntilInteraction flag — no data is stored until the visitor clicks. Showing a button to all visitors and checking agent availability does not require cookie consent under any major EU regulatory framework. Gating the entire boot command or the script loader behind Functional consent removes the chat capability entirely for visitors who may want it, and is more restrictive than regulations require.
---
Velaro Messenger (v20) — Automatic Consent Detection
> This section covers Velaro Messenger, the new Velaro platform. The configuration above applies to the Velaro Chat widget (v10). If you are not sure which platform your site uses, contact Velaro Support.
If your site uses Velaro Messenger, cookie consent handling is fully automatic. Add consentMode: "auto" to your embed configuration and Velaro detects your consent management platform and wires all consent handling — no additional developer work required.
Because consent is managed internally rather than through script blocking, there is no OtAutoBlock categorization issue with Velaro Messenger, and no need to modify OneTrust Auto-Blocking settings.
Supported platforms for auto-detection: OneTrust, Cookiebot, Osano, Termly, Usercentrics, CookieScript.
Standard embed:
<script src="https://messaging.velaro.com/messenger/embed.js"
data-site-id="YOUR_SITE_ID"
data-consent-mode="auto"
async></script>
What consentMode: "auto" does:
- Checks whether any supported CMP is already loaded on the page and wires it immediately
- If the CMP loads after Velaro (common with async loading), polls with exponential backoff for up to 10 seconds
- Maps your CMP's category decisions to Velaro's consent categories — analytics, functional, personalization
- If no CMP is detected within 10 seconds, grants all consent so the widget works normally
- Responds immediately when the visitor changes their preference — no page reload required
Consent mode options:
| Mode | What it does |
|---|---|
"auto" | Auto-detects and wires your CMP — recommended for OneTrust, Cookiebot, Osano, Termly, Usercentrics, CookieScript |
"defer" | Grants all consent the moment the visitor clicks the chat bubble, regardless of banner choice |
"require" | Manual callback — your developer calls the onConsentRequired function with grant decisions |
"none" (default) | No consent management — all tracking fires immediately on page load |
Contact Velaro Support if you need the exact embed.js URL for your deployment.
---
Legal Context
> This is not legal advice. Consult your legal counsel for guidance specific to your organization.
GDPR / ePrivacy (Europe): The trigger for consent is "storing or accessing information on a device." A chat widget that renders a button on screen but writes nothing to the browser until the visitor clicks does not store or access information on page load — it is visually present but data-dormant. The click-to-chat interaction is the user-initiated action that activates data collection. German, Dutch, and French DPA guidance confirms this interpretation. Using deferLoadUntilInteraction: true and classifying the shim as Strictly Necessary (C0001) is consistent with this interpretation and defensible to a DPO.
§25 TDDDG (Germany): The TDDDG (formerly TTDSG) requires informed consent for storing or accessing information on end devices. A chat button that displays without storing or accessing anything does not trigger this requirement. Storage begins at the moment the visitor clicks — an explicit user action that satisfies the "informed, voluntary" requirement of §25 TDDDG(1).
CCPA (California): CCPA regulates the sale or sharing of personal information, not the rendering of UI elements. A chat widget that does not process personal data until the visitor initiates a conversation is generally outside the scope of CCPA consent requirements.
What "Strictly Necessary" means for the shim: With deferLoadUntilInteraction, the shim script does one thing: show a button and check agent availability. It writes nothing. It registers no visitor. Classifying it as Strictly Necessary is accurate — it is necessary to provide the chat service the site owner has decided to offer, and it performs no tracking function.
---
Summary: Which Option Is Right for You?
| Your situation | Recommended option |
|---|---|
| DPO requires nothing run before an explicit user action; chat button must be visible to all visitors including Strictly Necessary | deferLoadUntilInteraction: true (Option 2) + change shim to C0001 in OneTrust |
| Compliance scanner flags tracking on page load; proactive invites not needed | deferStorageUntilInteraction: true (Option 1) |
| You use proactive invites; you have a consent banner your developer can modify | privacyConsent wired to your banner (Option 3) |
| You want zero data before interaction AND full respect for rejections | Options 1 and 3 combined (Option 4) |
| You load Velaro via GTM and the bubble is hidden for Strictly Necessary visitors | Fix the GTM trigger and change shim to C0001 in OneTrust Auto-Blocking — see GTM section |
| You use Velaro Messenger (new platform) | consentMode: "auto" — one line, no wiring needed |
| Your site has no cookie consent requirement | No change needed |
---
Frequently Asked Questions
Does the chat button disappear if a visitor rejects cookies?
With deferLoadUntilInteraction (Option 2): No — the button always appears and shows agent availability to all visitors regardless of cookie choice. Consent affects tracking, not visibility.
With deferStorageUntilInteraction (Option 1) alone: No. The bubble appears for all visitors.
With privacyConsent (Option 3) and done(false) on rejection: The bubble still appears, but clicking opens a popout window rather than the inline experience.
Will agents still see the visitor's page history?
With deferLoadUntilInteraction only: agents see the pages visited from the moment the visitor clicked to open chat. Pages visited before clicking are not recorded.
With privacyConsent and acceptance: full page history is available once the visitor accepts, beginning from that moment in the current session.
Does this make my site fully GDPR compliant?
These options address the specific concern of writing tracking data before consent or user interaction. Whether your overall implementation is compliant depends on your legal obligations, your consent banner configuration, your data processing agreements with Velaro, and other factors. Consult your legal counsel.
Do I need to update anything in my Velaro account or admin console?
No. These are client-side embed code changes only. No server-side settings need to change.
Can visitors who rejected cookies later accept and get full tracking?
Yes, when using the privacyConsent callback. When the visitor updates their preference — typically via a Cookie Settings link in your site footer — the callback fires again with true and tracking loads immediately in that session without a page reload.
I tried adding data-ot-ignore to the shim script in GTM and now nothing works, even with Functional cookies accepted.
This is a known issue with data-ot-ignore. When OtAutoBlock is told to skip a script via data-ot-ignore, it also skips adding it to its internal allow-list. The widget's iframe then cannot communicate with the parent page, and the widget fails silently — no bubble, no network calls, no errors visible in the console. Remove data-ot-ignore and fix the root cause instead: change the shim category to Strictly Necessary (C0001) in OneTrust Auto-Blocking.
I load Velaro through GTM. Does the boot command need to be in a separate tag from the shim script?
They can be in the same tag or separate tags. What matters is that neither tag has a consent condition that prevents it from firing for Strictly Necessary visitors, and that the shim URL is classified as C0001 in OneTrust Auto-Blocking when using deferLoadUntilInteraction. The consent handling belongs inside the boot command, not on the GTM trigger.
For implementation assistance, contact Velaro Support and tell us which consent platform your site uses.
Was this article helpful?