Skip to content

Record consent

EdgeKit stores no consent state about a user. There is no consent field on the user record or on a user’s site attachment. Consent is recorded as events instead:

  • your consent management platform runs the consent screen;
  • the tracker sends events only once your page lets it;
  • each event can carry proof of what the user agreed to, and every event carries the lawful basis you declared.

Your organization is the controller of this data, so the basis and the consent screen are yours to decide.

Every event EdgeKit collects carries consent_basis in EdgeKit’s own request entity (iglu:cloud.edgekit/request/jsonschema/1-0-0): the lawful basis declared for the event’s site when it was collected. It is one of:

  • strictly_necessary, the default;
  • consent_required.

The basis is set for your organization, and a site can override it. Staging refuses a basis that is not one of the two values, for your organization or for a site. The basis is not shown or edited in the console; ask EdgeKit to change it. Like other settings, a change reaches events from the next deploy on. Because the basis is stored on each event, a report run later shows what was declared when each event was collected.

The basis does not change what is collected. The collector accepts every event under either basis and never checks consent. Holding events back is the tracker’s job, on your page.

The tracker does not read your consent basis. On a site whose basis is consent_required, create it with requireConsent: true:

import { createTracker } from '@edgekitcloud/analytics-browser';
const analytics = createTracker({
siteId: 'site_example',
requireConsent: true,
});
analytics.trackPageView(); // held in memory, not sent
// From your consent management platform:
analytics.grantConsent(); // sends the held events in order, then sends new ones at once
analytics.revokeConsent(); // see below
  • Until grantConsent(), every track* call is held in memory. Held events are lost if the page unloads first.
  • grantConsent() sends the held events in the order they were tracked, then sends every new event straight away. Without requireConsent it does nothing, so a page can call it whatever the site’s basis.
  • revokeConsent() drops held events and clears the identifiers the tracker keeps in cookies and local storage, the user id included. With requireConsent, events are held again until the next grantConsent(). Without it, tracking goes on under new identifiers.
  • setUserId() takes effect at once, even while consent is pending, and sends nothing by itself.

revokeConsent() is not erasure: events already collected are kept. Before consent, anonymousTracking: true switches the tracker to its cookie-free mode.

See createTracker and EdgeKitTracker.

Attach a consent_document entity to an event to record which consent document the user agreed to. Its schema is built in: id and version are required strings, and name and description are optional strings or null.

const consent = {
schema:
'iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0',
data: {
id: 'privacy-policy',
version: '2026-09',
name: 'Privacy policy',
description: null,
},
};
analytics.trackPageView({ context: [consent] });

To record the user’s choice as an event of its own, add an event schema for it in Analytics › Configuration › Schemas, your schema registry. Then track it with trackSelfDescribingEvent and attach the same entity. An event or entity that does not match its schema, or names a schema your schema registry does not hold, is still answered 200 and is kept apart as invalid rather than stored with your events.

  • A refusal. With requireConsent, nothing is sent before grantConsent(), so a user who declined sends no events at all. A user who declined and a page with no tracker look the same.
  • Newsletter consent. Whether a user is on a newsletter list is its own record, kept per list. Agreeing to analytics subscribes nobody, and subscribing to a list records no analytics consent.