developer

Privacy & Data Handling

The Hood Web SDK is built with privacy by design.

This page explains what data the SDK stores, how it behaves with or without consent, and what developers need to configure in their Consent Management Provider (CMP).

Our goal is to keep integration simple while remaining fully compliant with GDPR and other privacy standards — without unnecessary legal complexity.

Overview

Almost no cookies

The SDK keeps its data in browser storage rather than cookies. There is one exception: when site-wide push subscription is used, a single first-party cookie _ocpsh is set with the constant value 1. It records that this browser is already subscribed so that sibling subdomains do not re-subscribe the same visitor. It carries no identifier, lasts 180 days, and is set as SameSite=Lax (plus Secure over HTTPS).

Enabling push_enable_subdomain_subscription replaces this cookie with a per-origin localStorage flag, in which case the SDK sets no cookies at all.

Apart from that cookie, all data is stored directly in the browser using:

  • sessionStorage – temporary data automatically removed at the end of a browser session
  • localStorage – persistent data such as consent preferences and technical keys that last between sessions

All SDK data is kept under a single storage key called _opc (lowercase).
Inside it, values are namespaced by your configuration tag, so several configurations on one page never overwrite each other.

Example structure:

{
  "_opc": {
    "YOUR_TAG_ID": {
      "uid": "1736412000.4821.0",
      "userConsent": { "analytics": true, "advertising": false, "functional": true, "consent": true }
    }
  }
}
Potential Key Conflict
If your application also writes to _opc in browser storage, set the storeKey configuration option to move the SDK to a different root key.

Storage Overview

GDPR — legal basis at a glance
  • Technical storage (session ID, A/B variants, dismissals) is necessary for service operation and does not require consent.
  • Processing that links data to a person (profile association via identity, campaign attribution) runs only with explicit consent. The SDK recognizes exactly four consent categories: analytics, advertising, functional and consent.
  • This page is developer guidance, not legal advice.
Storage TypeUsed ForLifetime
sessionStorageTemporary session trackingUntil the tab/browser is closed
localStoragePersistent SDK data stored under _opcUp to 365 days (or until manually cleared)

When no consent is given, the SDK will:

  • create a temporary session ID (random and non-persistent),
  • store it as uid inside sessionStorage,
  • use it to group analytics events within the same browser session.

This ID is deleted automatically when the session ends.
It cannot identify a user and does not require consent.

Example session data:

{
  "_opc": {
    "YOUR_TAG_ID": {
      "uid": "1736412000.4821.0"
    }
  }
}

This allows the SDK to measure simple things like page views or event counts — fully anonymous.

If the user gives consent via your CMP, the SDK can:

  • keep the consent state,
  • track campaign parameters (utm_*) and push permission data,
  • associate events to a server-side profile when your app calls identity (optional).

Example flow:

Hood('consent', { analytics: true });
Hood('identity', 'user_12345');
Hood('trackEvent', 'purchase', { value: 25 });

If consent is later withdrawn, the SDK will stop using identifiable data and continue with anonymous session tracking only.

Identity — server-side only
  • identity payloads are never stored in the browser.
  • Send identity only when you have consent (for example, analytics: true) and do it consistently on login/auth so events can be linked across sessions.
  • We generate and manage the internal profile ID server-side; your external ID is attached to that profile as an attribute.

What Data Is Stored

All data is stored under the single key _opc, namespaced by configuration tag. The subkeys below are relative to _opc.<tag>.

SubkeyStoragePurposePurpose KeyLifetimeConsent Required
uidsessionStorageTemporary anonymous visitor IDtechnicalUntil session ends
uid + ttllocalStoragePersistent visitor ID and its expiryanalyticsUp to 1 year
userConsentlocalStorageConsent states per categorytechnicalUntil changed
utm_*localStorageCampaign and attribution parametersanalyticsUntil overwritten
pushlocalStoragePush subscription flag, only when push_enable_subdomain_subscription is enabled (otherwise the _ocpsh cookie is used)technicalUntil overwritten
m_<modalId>.*localStoragePer-modal view counters, timestamps and A/B varianttechnicalUntil overwritten
webpush_dismissalslocalStorageCount of dismissed push promptstechnicalUntil overwritten

The SDK includes a simple consent interface that should be synced with your CMP.

Pass consent states directly from your CMP, using the SDK’s four category names:

Hood('consent', {
  analytics: true,
  advertising: false,
  functional: true,
  consent: true
});

Passing a boolean sets all four categories at once, which is a convenient shorthand for an accept-all or reject-all button:

Hood('consent', true);
Unknown categories are silently ignored
Only analytics, advertising, functional and consent are recognized. Keys such as marketing, personalization, push or enabled are dropped without warning, so a CMP mapping that uses them grants nothing.

If the user updates consent:

Hood('consent', newConsentState);

Only categories whose value actually changes trigger a consent event, so re-sending the same state is harmless.

Clearing Data

For “right to be forgotten” or user data removal:

Hood('identity', null);
Hood('consent', { analytics: false, advertising: false, functional: false, consent: false });

Revoking analytics clears the persistent visitor ID and stored campaign parameters from localStorage.

CMP Configuration Guide

In your Consent Management Provider (CMP), define the following categories and map them to the SDK purpose keys:

PurposePurpose KeyWhen ActiveDescription
Analyticsanalyticsanalytics: trueAnalytics beacons, the persistent visitor ID, and campaign attribution (UTM storage)
Advertisingadvertisingadvertising: trueAdvertising-related processing
Functionalfunctionalfunctional: trueFunctional storage beyond what is strictly necessary
Overallconsentconsent: trueThe visitor’s overall consent decision
Campaign attribution is gated by analytics
UTM parameters are stored under the analytics category, not a separate marketing category. If your CMP models marketing separately, map that choice onto analytics (or advertising) when calling Hood('consent', …).
IAB TCF is detected automatically
When a TCF-compatible CMP is present, the SDK reads its decision and derives these categories itself, so an explicit Hood('consent', …) call is not required. The TC string is included as proof alongside the consent event.
Technical vs. consented data
Everything else (session tracking, A/B testing, modal dismissals) is purely technical and not personally identifiable.

Best Practices

  • Send consent to the SDK immediately after your CMP loads
  • Linking events to a person happens server-side via identity and requires consent (no user IDs are stored locally)
  • No data passed via identity() / setUserProperties() is saved locally
  • Use unique key names if your app also writes to localStorage
  • Keep your SDK up to date — privacy rules evolve

Quick Reference

Use CaseRequires ConsentStorage
Counting sessionssessionStorage (uid)
Measuring page viewsanalytics beacons are suppressed without analytics consent
Linking events to a userserver-side only (no local storage)
Remembering a push subscription_ocpsh cookie, or localStorage (push) in per-subdomain mode
A/B testing modalslocalStorage (m_<modalId>.ab)
Tracking campaigns (UTM)localStorage (utm_*)

Summary

  • All SDK data is stored under a single key _opc in browser storage, namespaced by configuration tag.
  • The only cookie is _ocpsh, a constant non-identifying push subscription flag that can be turned off with push_enable_subdomain_subscription.
  • Persistent data (the visitor ID and UTM parameters) is stored only with analytics consent.
  • The push subscription flag is a functional check — never a user identifier.
  • The SDK recognizes four consent categories: analytics, advertising, functional, consent.

Need more technical details?
Check our Integration Guide or contact our support team.