All Skills

Core concepts for Fullstory's User Consent APIs. Platform-agnostic guide covering consent mechanisms, GDPR/CCPA compliance patterns, and privacy-compliant session recording. See SKILL-WEB.md and SKILL-MOBILE.md for implementation examples.

E
$npx skills add fullstorydev/fs-skills --skill fullstory-user-consent

Fullstory User Consent API

Implementation Files: This document covers core concepts. For code examples, see:

Overview

Fullstory's User Consent APIs allow developers to implement privacy-compliant session recording by conditioning capture on explicit user consent. This is essential for:

  • GDPR Compliance: Obtain consent before recording EU users
  • CCPA Compliance: Allow California users to opt-out
  • App Store Compliance: Respect iOS App Tracking Transparency (ATT)
  • Privacy Controls: Give users control over their data
  • Selective Capture: Record only users who have consented

Core Concepts

Fullstory provides two mechanisms for consent, each serving different use cases:

ApproachPurposePlatform Notes
Holistic ConsentDelay ALL capture until consentWeb: _fs_capture_on_startup = false + FS('start')
Element-Level ConsentCapture specific elements only with consentWeb only: Elements marked "Capture with consent" in Fullstory UI

For most compliance scenarios (GDPR, CCPA, ATT), use holistic consent:

  1. Delay capture on startup — SDK loads but doesn't record
  2. Show consent UI — Banner, dialog, or settings
  3. Start capture on consent — Begin recording after user agrees
  4. Stop capture on revocation — Respect user's withdrawal
┌─────────────┐  User Accepts  ┌─────────────┐
│  Not        │ ─────────────► │  Capture    │
│  Capturing  │                │  Active     │
└─────────────┘                └─────────────┘
      ▲                              │
      │       User Withdraws        │
      └──────────────────────────────┘

Consent state should be:

  • Persisted — Saved to storage (localStorage, UserDefaults, SharedPreferences)
  • Restored — Checked on app/page load
  • Synchronized — Consistent across the application

API Methods by Platform

PlatformDelay CaptureStart CaptureStop Capture
Web_fs_capture_on_startup = falseFS('start')FS('shutdown')
iOSFSDelegate / ConfigFS.restart()FS.shutdown()
AndroidConfigFS.restart()FS.shutdown()
FlutterConfigFS.restart()FS.shutdown()
React NativeConfigFullStory.restart()FullStory.shutdown()

Platform-Specific Considerations

Web (Browser)

  • Cookie consent banners (GDPR)
  • Consent Management Platforms (CMPs): OneTrust, CookieBot, etc.
  • IAB TCF v2 compliance
  • localStorage for consent persistence

iOS

  • App Tracking Transparency (ATT) framework
  • requestTrackingAuthorization for iOS 14.5+
  • UserDefaults for consent persistence
  • Privacy nutrition labels in App Store

Android

  • No system-level tracking prompt (unlike iOS ATT)
  • App-level consent dialogs
  • SharedPreferences for consent persistence
  • Google Play data safety section

Flutter / React Native

  • Cross-platform consent UI
  • Platform-specific storage adapters
  • Unified consent logic

Compliance Guidance

GDPR (EU)

RequirementImplementation
Consent before trackingDelay capture until consent
Right to withdrawProvide consent revocation in settings
Record consentStore timestamp and method
Clear explanationExplain what Fullstory does

CCPA (California)

RequirementImplementation
Opt-out rightProvide "Do Not Sell" option
Notice at collectionExplain data collection
Verifiable requestsSupport data access/deletion

iOS App Tracking Transparency

RequirementImplementation
ATT promptRequest authorization before tracking
Respect denialDon't capture if user denies
Usage descriptionExplain tracking in Info.plist

Best Practices

1. Default to Not Capturing

For maximum compliance, don't capture until explicit consent:

Start: Capture disabled
User consents: Start capture
User logged in: Identify + capture

Store consent decision and restore on subsequent launches:

1. Check stored consent on app/page load
2. If granted: start capture immediately
3. If denied: remain disabled
4. If unknown: show consent UI

3. Provide Withdrawal Mechanism

Users must be able to revoke consent:

  • Settings page toggle
  • Privacy preferences
  • "Manage cookies" link (web)

Coordinate consent and identification:

1. Check consent status
2. If consented and user logged in: identify user
3. If consented and anonymous: capture anonymously
4. If not consented: don't capture or identify

Keep records of consent grants:

  • Timestamp
  • Method (banner, settings, etc.)
  • User agent / device info
  • Version of consent language

Troubleshooting

CauseSolution
SDK not loadedVerify SDK initialization
Wrong API calledUse start()/restart(), not just consent flag
User on excluded page/screenCheck exclusion rules
CauseSolution
Consent not recordedAdd user property consentGranted: true
No audit trailLog consent grants to backend
CauseSolution
Not saved to storagePersist to localStorage/UserDefaults/SharedPreferences
Storage clearedHandle storage unavailable gracefully
Cross-origin issues (web)Use same-origin storage

Key Takeaways for Agent

When helping developers with Consent APIs:

  1. Always emphasize:
    • Delay capture by default for GDPR compliance
    • Persist consent to storage
    • Provide withdrawal mechanism
    • Coordinate consent with identification
  2. Common mistakes to watch for:
    • Capturing before consent
    • Not persisting consent
    • No withdrawal option
    • Ignoring CMP/ATT status
    • Race conditions with identity
  3. Questions to ask developers:
    • What regulations apply (GDPR, CCPA, ATT)?
    • Do you have an existing CMP?
    • How do users currently consent?
    • Is there a privacy settings page?
  4. Platform routing:
    • Web (JavaScript/TypeScript) → See SKILL-WEB.md
    • iOS (Swift/SwiftUI) → See SKILL-MOBILE.md § iOS
    • Android (Kotlin) → See SKILL-MOBILE.md § Android
    • Flutter (Dart) → See SKILL-MOBILE.md § Flutter
    • React Native → See SKILL-MOBILE.md § React Native