Privacy Labs Flutter Consent SDK
DPDP-compliant consent management SDK for Flutter apps.
Installation
Add to your pubspec.yaml:
dependencies:
theprivacylabs_consent: ^0.1.1
Then run:
flutter pub get
Quick Start
1. Initialize the SDK
import 'package:theprivacylabs_consent/theprivacylabs_consent.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PrivacyLabsConsent.init(ConsentConfig(
orgId: 'your-org-id', // From Privacy Labs dashboard
onConsentChange: (consent) {
print('Consent changed: ${consent.preferences.toJson()}');
// Enable/disable analytics based on consent
if (consent.preferences.analytics) {
Analytics.enable();
} else {
Analytics.disable();
}
},
onError: (error) {
print('Consent error: $error');
},
debug: kDebugMode, // Enable debug logs in development
));
runApp(MyApp());
}
2. Create Privacy Settings Screen
import 'package:flutter/material.dart';
import 'package:theprivacylabs_consent/theprivacylabs_consent.dart';
class PrivacySettingsScreen extends StatefulWidget {
@override
_PrivacySettingsScreenState createState() => _PrivacySettingsScreenState();
}
class _PrivacySettingsScreenState extends State<PrivacySettingsScreen> {
List<ConsentCategory> _categories = [];
ConsentState? _consent;
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadData();
}
Future<void> _loadData() async {
final categories = await PrivacyLabsConsent.getCategories(lang: 'en');
final consent = await PrivacyLabsConsent.getConsentStatus();
setState(() {
_categories = categories;
_consent = consent;
_isLoading = false;
});
}
Future<void> _updateConsent(String categoryId, bool value) async {
final current = _consent?.preferences ?? ConsentPreferences();
ConsentPreferences updated;
switch (categoryId) {
case 'analytics':
updated = current.copyWith(analytics: value);
break;
case 'marketing':
updated = current.copyWith(marketing: value);
break;
case 'performance':
updated = current.copyWith(performance: value);
break;
default:
return;
}
await PrivacyLabsConsent.setConsent(updated);
await _loadData(); // Refresh state
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return Scaffold(
appBar: AppBar(title: Text('Privacy Settings')),
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(title: Text('Privacy Settings')),
body: ListView(
padding: EdgeInsets.all(16),
children: [
Text(
'Control how we use your data',
style: Theme.of(context).textTheme.bodyLarge,
),
SizedBox(height: 24),
// Category toggles
..._categories.map((category) => Card(
child: SwitchListTile(
title: Text(category.name),
subtitle: Text(category.description),
value: _getCategoryValue(category.id),
onChanged: category.required
? null
: (value) => _updateConsent(category.id, value),
),
)),
SizedBox(height: 24),
// Accept All button
ElevatedButton(
onPressed: () async {
await PrivacyLabsConsent.acceptAll();
await _loadData();
},
child: Text('Accept All'),
),
],
),
);
}
bool _getCategoryValue(String categoryId) {
if (_consent == null) return false;
switch (categoryId) {
case 'essential':
return true;
case 'analytics':
return _consent!.preferences.analytics;
case 'marketing':
return _consent!.preferences.marketing;
case 'performance':
return _consent!.preferences.performance;
default:
return false;
}
}
}
3. Link Identity After Login
// After user logs in
Future<void> handleLogin(String email, String password) async {
final user = await authService.login(email, password);
// Link consent to user identity for cross-device sync
await PrivacyLabsConsent.linkIdentity(
email,
method: IdentityLinkMethod.login,
);
}
// After user signs up
Future<void> handleSignup(String email, String password) async {
final user = await authService.signup(email, password);
await PrivacyLabsConsent.linkIdentity(
email,
method: IdentityLinkMethod.signup,
);
}
4. iOS App Tracking Transparency (Optional)
For iOS apps that use tracking, you need to request ATT permission:
import 'dart:io';
import 'package:theprivacylabs_consent/theprivacylabs_consent.dart';
Future<void> requestTrackingPermission() async {
if (Platform.isIOS) {
// Request ATT permission first
final attStatus = await PrivacyLabsConsent.requestATTPermission();
if (attStatus == ATTStatus.authorized) {
// User allowed tracking, show privacy settings
Navigator.pushNamed(context, '/privacy-settings');
} else {
// User denied tracking, set consent accordingly
await PrivacyLabsConsent.setConsent(ConsentPreferences(
analytics: false,
marketing: false,
));
}
} else {
// Android: just show privacy settings
Navigator.pushNamed(context, '/privacy-settings');
}
}
Note: ATT requires the app_tracking_transparency package for full support.
API Reference
PrivacyLabsConsent
| Method | Description |
|---|---|
init(config) |
Initialize the SDK |
getConsentStatus({syncWithServer}) |
Get current consent state |
hasConsent(category) |
Check if user consented to a category |
getCategories({lang}) |
Get available consent categories |
setConsent(preferences) |
Update consent preferences |
acceptAll() |
Accept all categories |
withdrawConsent() |
Withdraw all consent |
linkIdentity(userKey, {method}) |
Link consent to user identity |
syncFromServer(userId) |
Sync consent from another device |
requestATTPermission() |
Request iOS ATT permission |
getATTStatus() |
Get iOS ATT status |
clearLocalData() |
Clear local consent data |
Types
ConsentConfig
ConsentConfig({
required String orgId,
String apiBaseUrl = 'https://app.theprivacylabs.com',
bool debug = false,
void Function(ConsentState)? onConsentChange,
void Function(Exception)? onError,
})
ConsentPreferences
ConsentPreferences({
bool essential = true,
bool analytics = false,
bool marketing = false,
bool performance = false,
})
ConsentState
ConsentState({
required bool hasConsent,
required ConsentPreferences preferences,
DateTime? timestamp,
DateTime? expiryDate,
String? platform,
String? deviceId,
bool isSynced = false,
})
Cross-Device Consent Sync
When a user logs in on a new device, their consent preferences are automatically synced:
- User gives consent on Device A (web or mobile)
- User logs in on Device B (Flutter app)
- SDK calls
linkIdentity()with user's email - Backend finds existing consent and syncs to Device B
onConsentChangecallback fires with synced preferences
This ensures consistent consent across all user devices.
Integration Checklist
Before Launch
Add SDK to pubspec.yamlInitialize SDK in main.dart with orgIdCreate Privacy Settings screen with category togglesAdd "Withdraw Consent" button that callswithdrawConsent()(clears local data + records to API)Add "Privacy Settings" to app settings/profile menu
On User Events
First app launch: Check consent status, show settings if neededUser login: CalllinkIdentity(email, method: IdentityLinkMethod.login)User signup: CalllinkIdentity(email, method: IdentityLinkMethod.signup)User logout: Optionally callclearLocalData()
SDK Integration
Gate analytics/marketing SDKs based on consent stateImplementonConsentChangecallback to enable/disable SDKs dynamicallySee SDK Integration Recipes below for per-SDK examples
SDK Integration Recipes
Important: Mobile SDKs are compiled into your app — you cannot "not load" them at runtime. Instead, consent controls whether each SDK collects data or not. Your app owns execution; Privacy Labs owns consent state + policy.
Firebase Analytics
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:theprivacylabs_consent/theprivacylabs_consent.dart';
// On app launch — set initial state
final consent = await PrivacyLabsConsent.getConsentStatus();
await FirebaseAnalytics.instance
.setAnalyticsCollectionEnabled(consent?.preferences.analytics ?? false);
// On consent change — update dynamically
await PrivacyLabsConsent.init(ConsentConfig(
orgId: 'your-org-id',
onConsentChange: (state) async {
await FirebaseAnalytics.instance
.setAnalyticsCollectionEnabled(state.preferences.analytics);
},
));
Firebase Crashlytics
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
// Gate on analytics (or performance) consent
await FirebaseCrashlytics.instance
.setCrashlyticsCollectionEnabled(consent?.preferences.analytics ?? false);
Mixpanel
import 'package:mixpanel_flutter/mixpanel_flutter.dart';
final mixpanel = await Mixpanel.init('YOUR_TOKEN', trackAutomaticEvents: false);
// On consent change
if (consent.preferences.analytics) {
mixpanel.optInTracking();
} else {
mixpanel.optOutTracking();
}
Adjust (Marketing Attribution)
import 'package:adjust_sdk/adjust.dart';
import 'package:adjust_sdk/adjust_config.dart';
final adjustConfig = AdjustConfig('APP_TOKEN', AdjustEnvironment.production);
// Only enable if marketing consent given
if (consent?.preferences.marketing ?? false) {
Adjust.start(adjustConfig);
} else {
Adjust.setEnabled(false);
}
// On consent change
onConsentChange: (state) {
Adjust.setEnabled(state.preferences.marketing);
}
AppsFlyer
import 'package:appsflyer_sdk/appsflyer_sdk.dart';
// Gate on marketing consent
if (consent?.preferences.marketing ?? false) {
appsflyerSdk.startSDK();
} else {
appsflyerSdk.stop(true);
}
CleverTap / MoEngage (Marketing Push)
// CleverTap
import 'package:clevertap_plugin/clevertap_plugin.dart';
if (consent?.preferences.marketing ?? false) {
CleverTapPlugin.setOptOut(false);
} else {
CleverTapPlugin.setOptOut(true);
}
// MoEngage
import 'package:moengage_flutter/moengage_flutter.dart';
if (consent?.preferences.marketing ?? false) {
MoEngageFlutter.enableDataTracking();
} else {
MoEngageFlutter.disableDataTracking();
}
Pattern: Consent-Gated Helper
// utils/consent_gate.dart
import 'package:theprivacylabs_consent/theprivacylabs_consent.dart';
Future<void> ifConsented(String category, Future<void> Function() action) async {
final consent = await PrivacyLabsConsent.getConsentStatus();
final prefs = consent?.preferences;
bool allowed = false;
switch (category) {
case 'analytics':
allowed = prefs?.analytics ?? false;
break;
case 'marketing':
allowed = prefs?.marketing ?? false;
break;
case 'performance':
allowed = prefs?.performance ?? false;
break;
}
if (allowed) {
await action();
}
}
// Usage
await ifConsented('analytics', () => FirebaseAnalytics.instance.logEvent(name: 'purchase'));
await ifConsented('marketing', () => Adjust.trackEvent(adjustEvent));
License
MIT
Libraries
- theprivacylabs_consent
- Privacy Labs Flutter Consent SDK