Age-Based Consent Management: Handling Age Verification with Transcend
This guide explains how to use Transcend’s Consent & Preference Management solutions to implement age-based consent rules — such as automatically blocking advertising and data sharing for minors.
Many privacy regulations (COPPA, GDPR, state-level US laws) require organizations to apply stricter consent rules for minors. With Transcend, you can implement age-based consent enforcement across three layers of your stack:
| Layer | What It Does | Where It Lives |
|---|---|---|
| 1. Client-Side Override | Intercepts and blocks network requests & cookies tagged with specific consent purposes (e.g., SaleOfInfo, Advertising) | Browser — runs inside airgap.js |
| 2. Preference Store | Stores user birth date as metadata, syncs it to the web client for use in client-side logic | Transcend backend |
| 3. Downstream Systems | Propagates consent changes to third-party systems (CRMs, ad platforms, CDPs) via workflow triggers | Transcend integrations layer |
These three layers work together: the Preference Store provides the age data, the client-side override enforces consent rules in real time in the browser, and downstream workflow triggers ensure that the same consent decisions are reflected across your entire data ecosystem.
The first layer of enforcement lives in the browser. Using airgap.js’s override API, you can intercept all pending network requests and cookie mutations and apply custom logic — such as blocking requests tagged with SaleOfInfo or Advertising purposes when the user is a minor.
See the airgap.js API Reference for full override documentation.
- airgap.js intercepts every network request and cookie mutation before it executes.
- Your override snippet checks whether the current user is a minor.
- If the user is a minor and the request is tagged with restricted purposes, the override calls
event.deny()to block it.
Place this snippet before the airgap.js script tag, or use the Airgap Prefix approach (see the note below).
const MINOR_RESTRICTED_PURPOSES = ['SaleOfInfo', 'Advertising'];
let _isMinorCached = undefined;
function getMinorStatus() {
if (_isMinorCached !== undefined) return _isMinorCached;
const consent = self.airgap?.getConsent?.();
const birthDate = consent?.metadata?.birthDate;
if (!birthDate) {
_isMinorCached = false;
return false;
}
const birth = new Date(birthDate);
const today = new Date();
const age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
const isMinor = (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate()))
? age - 1 < 18 : age < 18;
_isMinorCached = isMinor;
return isMinor;
}
(self.airgap = { overrides: [], ...self.airgap }).overrides.push({
override: (event) => {
if (getMinorStatus() && MINOR_RESTRICTED_PURPOSES.some((p) => event.purposes.has(p))) {
event.deny();
}
}
});
(self.airgap = { cookieOverrides: [], ...self.airgap }).cookieOverrides.push((event) => {
if (getMinorStatus() && MINOR_RESTRICTED_PURPOSES.some((p) => event.purposes.has(p))) {
event.deny();
}
});Performance note: The getMinorStatus() function is memoized — it calculates the minor status once and caches the result.
| Approach | Script Tags | Maintenance |
|---|---|---|
| Override snippet (DIY) | 2 scripts per site | You maintain the snippet |
| Airgap prefix (managed) | 1 script per site | Transcend manages it |
| Source | How It Works | Best For |
|---|---|---|
| Your own database | Your app sets a global variable (e.g., window.__userBirthDate) on login | Organizations that already store DOB |
| Transcend Preference Store | Birth date stored as metadata; read via airgap.getConsent().metadata.birthDate | Centralized consent + age data |
Transcend’s Preference Store supports a metadata field on each consent record. You can use this to store the user’s birth date alongside their consent preferences.
PUT /v1/preferences
{
"records": [{
"partition": "YOUR_PARTITION_ID",
"timestamp": "2026-01-15T00:00:00Z",
"identifiers": [{ "name": "email", "value": "user@example.com" }],
"purposes": [
{ "purpose": "Advertising", "enabled": false },
{ "purpose": "SaleOfInfo", "enabled": false }
],
"metadata": [{ "key": "birthDate", "value": "2010-03" }]
}]
}// Set birth date as consent metadata
airgap.setConsentMetadata(event, {
...(airgap.getConsent().metadata || {}),
birthDate: '2010-03'
});
// Sync consent + metadata to Preference Store
airgap.sync();Privacy Best Practice: Store birth date using month and year only (e.g., "2010-03") rather than the full date.
When a user’s consent changes, Transcend’s workflow triggers automatically push those changes to connected downstream systems. It's common to use a Custom Function to either a) notify downstream systems of a user's minor status or b) update other types of consent on the preference record to be opted out when a minor.
- Determine your age data source — your own DB or Transcend Preference Store.
- [Optional] Store birth date in Preference Store — use
metadata: [{ key: "birthDate", value: "YYYY-MM" }]. - Add the client-side override — snippet or airgap prefix.
- Define restricted purposes — e.g.,
SaleOfInfo,Advertising. - [Optional] Connect downstream systems — configure workflow triggers.
- Test the implementation — verify blocking for minors, unaffected adults, end-to-end flow.
Transcend has experimental support for automated workflows that trigger when a minor turns 18, automatically updating consent purposes and propagating changes across all three layers. Please reach out to support@transcend.io if you are interested in learning more about this.