Ask for Consent

Collect user consent for Google Ads conversion tracking with minimal friction. The consent drawer appears only when users attempt conversion actions, preserving the gclid parameter for proper attribution.


Overview

Two components work together for flexible consent management:

Both integrate with @dynamic-type/analytics for GDPR-compliant consent collection:


Mark specific buttons/forms that require consent.

---
import { ConsentDrawer } from "@dynamic-type/ddi";
---

<!-- Add ConsentDrawer once per page -->
<ConsentDrawer privacyPolicyUrl="/integritetspolicy" />

<!-- Any button requiring consent -->
<button data-ddi-requires-consent data-ddi-event="book-appointment">
    Boka tid
</button>

How it works:

  1. User clicks button
  2. If consent not given: Drawer opens, button action blocked
  3. User accepts/rejects in drawer
  4. Original button action resumes

Usage Pattern 2: Automatic Internal Navigation

Ask for consent on ALL internal link clicks automatically.

---
import { ConsentDrawer, AskForConsentOnInternalNavigation } from "@dynamic-type/ddi";
---

<ConsentDrawer privacyPolicyUrl="/integritetspolicy" />
<AskForConsentOnInternalNavigation />

<!-- These links will automatically trigger consent if not given -->
<a href="/behandlingar">Se alla behandlingar</a>
<a href="/kontakt">Kontakta oss</a>
<a href="/boka">Boka tid</a>

<!-- External links are NOT affected -->
<a href="https://external.com">External site</a>

How it works:


Example 3: Form Submission

Collect consent before form data is sent:

<ConsentDrawer privacyPolicyUrl="/integritetspolicy" />

<form action="/submit-contact" method="POST" data-ddi-requires-consent>
    <input type="email" name="email" required />
    <button type="submit">Skicka</button>
</form>

Behavior:


Example 4: Combining Both Patterns

Use both explicit CTA consent AND automatic internal navigation consent:

---
import { ConsentDrawer, AskForConsentOnInternalNavigation } from "@dynamic-type/ddi";
---

<ConsentDrawer privacyPolicyUrl="/privacy" />
<AskForConsentOnInternalNavigation />

<!-- Explicit CTA consent -->
<button data-ddi-requires-consent>Boka nu</button>

<!-- Internal links automatically require consent -->
<a href="/behandlingar">Se behandlingar</a>
<a href="/kontakt">Kontakta oss</a>

<!-- Forms can also require consent -->
<form data-ddi-requires-consent>...</form>

Behavior:


Components

ConsentDrawer

The drawer UI that displays consent options. Required for both usage patterns.

Props:

Note: The consent text is hardcoded in Swedish for GDPR compliance and cannot be customized.

AskForConsent­OnInternalNavigation

Automatically intercepts ALL internal link clicks and asks for consent if not given.

Props: None

Usage:

<AskForConsentOnInternalNavigation />

This component uses delegated event handling (similar to EventObserver) to intercept all internal link clicks on the page. It detects internal vs external links the same way as track-event-handler.ts.


Attributes for Tracked Elements

Add to buttons or forms that should explicitly trigger consent:

Note:


Swedish Text Content

Default drawer text adapts to context:

For explicit CTAs (buttons, forms):

Innan du går vidare

För att utvärdera och förbättra vår marknadsföring använder vi en cookie som kopplar ditt besök till annonsen som ledde dig hit.

Informationen är anonymiserad och delas endast med Google Ads för konverteringsmätning.

Genom att godkänna hjälper du oss förbättra tjänsten.

Läs mer i vår integritetspolicy

[Godkänn] [Neka]

For internal navigation:

Innan du går vidare till nästa sida

För att utvärdera och förbättra vår marknadsföring använder vi en cookie som kopplar ditt besök till annonsen som ledde dig hit.

Informationen är anonymiserad och delas endast med Google Ads för konverteringsmätning.

Genom att godkänna hjälper du oss förbättra tjänsten.

Läs mer i vår integritetspolicy

[Godkänn] [Neka]


How It Works Internally

  1. Page Load: ConsentDrawer checks currentConsent() from analytics
  2. User Clicks CTA/Link: Click event intercepted
  3. Consent Check:
    • If already answered: Proceed immediately
    • If not answered: Block action, show drawer
  4. User Decides: Clicks “Godkänn” or “Neka”
  5. Server Call: setConsent({ trackConversions: true/false }) sent to /set-consent
  6. Cookies Set:
    • dt-consent (readable) - User’s decision
    • dt-tracking (HttpOnly) - UUID
    • dt-gclid (HttpOnly, 90 days) - If consent given
    • dt-wbraid (HttpOnly, 90 days) - If consent given
  7. Resume Action: Original click handler executes
  8. Future Visits: Consent remembered, no drawer shown

Integration with Analytics

The consent components work seamlessly with @dynamic-type/analytics:

import { currentConsent } from "@dynamic-type/analytics/client";

// Check current consent status
const consent = currentConsent();
// Returns: undefined | { trackConversions: boolean }

// Consent is automatically sent to server
// No manual integration needed

GDPR Compliance

Prior consent obtained - Before any tracking cookies ✅ Freely given - User can reject and still use site ✅ Specific & informed - Clear purpose stated ✅ Unambiguous - Explicit button click required ✅ Revocable - User can change decision (future feature) ✅ Equal prominence - Accept/reject buttons equal size ✅ No dark patterns - Swedish IMY compliant


Display current consent status and allow users to change it (GDPR Article 7.3 - withdrawal must be as easy as giving consent):

---
import { ConsentStatus, ConsentDrawer } from "@dynamic-type/ddi";
---

<ConsentDrawer privacyPolicyUrl="/integritetspolicy" />

<!-- Typically placed in footer -->
<footer>
    <ConsentStatus />
</footer>

Component shows:

Props:

Accessibility:


Live Examples

Try clicking the buttons below to see the consent flow:

Consent Status - Always visible consent settings

This component shows your current consent status and lets you change it:

Try accepting/rejecting consent below, then see how the status updates.

Different elements triggering consent request

[Description]

Läs mer i vår integritetspolicy

Modal 1

This is the content of modal 1. You can now see how the consent drawer interacts with regular modals.

Modal 2

This is the content of modal 2. Notice how consent is only asked once - the second button won’t show the consent drawer if you already answered.