GDPR Compliance
Implement privacy-compliant tracking with consent management.
Overview#
Mobana is designed with privacy in mind:
- No device IDs: We don't collect IDFA, GAID, or other device identifiers.
- No personal data: The SDK doesn't collect names, emails, or other PII.
- Probabilistic matching: Attribution uses IP address, timezone, and screen size — not persistent identifiers.
- User control: The setTrackingEnabled() method lets users opt out at any time without affecting app functionality (flows still work).
Data Collected#
The SDK collects the following data:
- • Install ID: Random UUID generated on first launch
- • Platform: iOS or Android
- • Device signals: Timezone, screen dimensions, language
- • UTM parameters: From attribution redirect URLs
- • Referrer domain: Domain only (e.g., "facebook.com"), no full URL
- • Conversion events: Event names and values you track
- • Flow events: Flow interaction events
None of this data is personally identifiable on its own. The install ID is random and can be reset at any time.
Implementing Consent#
Check for Consent on Launch
App.tsx
// Show consent prompt before initializing SDK
async function handleAppStart() {
// Check if we've already asked for consent
const consentStored = await AsyncStorage.getItem('tracking_consent');
if (consentStored === null) {
// First launch - show consent prompt
navigation.navigate('ConsentScreen');
return;
}
// Initialize SDK based on stored consent
await Mobana.init({
appId: 'YOUR_APP_ID',
appKey: 'YOUR_APP_KEY',
enableTracking: consentStored === 'true',
});
}Consent Screen
ConsentScreen.tsx
// ConsentScreen.tsx
function ConsentScreen() {
const handleAccept = async () => {
await AsyncStorage.setItem('tracking_consent', 'true');
// Initialize with tracking enabled
await Mobana.init({
appId: 'YOUR_APP_ID',
appKey: 'YOUR_APP_KEY',
enableTracking: true,
});
navigation.navigate('Home');
};
const handleDecline = async () => {
await AsyncStorage.setItem('tracking_consent', 'false');
// Initialize with tracking disabled — flows still work normally
await Mobana.init({
appId: 'YOUR_APP_ID',
appKey: 'YOUR_APP_KEY',
enableTracking: false,
});
navigation.navigate('Home');
};
return (
<View>
<Text>We use attribution tracking to understand how users find our app.</Text>
<Button onPress={handleAccept}>Accept</Button>
<Button onPress={handleDecline}>Decline</Button>
</View>
);
}Allow Users to Change Consent
PrivacySettings.tsx
// Settings screen - allow users to change their mind
function PrivacySettings() {
const [trackingEnabled, setTrackingEnabled] = useState(false);
useEffect(() => {
AsyncStorage.getItem('tracking_consent').then(value => {
setTrackingEnabled(value === 'true');
});
}, []);
const handleToggle = async (enabled: boolean) => {
setTrackingEnabled(enabled);
await AsyncStorage.setItem('tracking_consent', String(enabled));
// Update SDK state
Mobana.setTrackingEnabled(enabled);
};
return (
<View>
<Text>Allow attribution tracking</Text>
<Switch value={trackingEnabled} onValueChange={handleToggle} />
</View>
);
}GDPR Data Subject Rights#
Right to Access
Users can request what data is collected:
// Handle GDPR data request
async function handleDataRequest() {
// installId is the only identifier Mobana holds server-side
const installId = await Mobana.getInstallId();
// getAttribution() returns all locally readable data Mobana has collected
const { attribution } = await Mobana.getAttribution();
return {
installId,
attribution, // UTM source/medium/campaign, confidence score — or null if no match
// Note: device signals used for probabilistic matching (timezone, screen size, IP)
// are not stored — they are only used transiently during the attribution request.
};
}Right to Erasure
Users can request data deletion:
// Handle GDPR data deletion request
async function handleDataDeletion() {
// Clear all local Mobana data
await Mobana.reset();
// Reset consent state
await AsyncStorage.removeItem('tracking_consent');
// Note: Server-side data is anonymized (only installId and UTM params)
// and can be deleted upon request to [email protected]
}For server-side data deletion, users should contact [email protected] with their install ID (available via getInstallId()).
SDK Behavior When Disabled#
When tracking is disabled via enableTracking: false or setTrackingEnabled(false):
- getAttribution() returns
{ status: 'error', error: { type: 'tracking_disabled' } } - trackConversion() is a no-op — conversions are silently dropped, not queued. Any conversions pending in the local queue (from before opt-out) are also discarded immediately.
- startFlow() and prefetchFlow() continue to work — flows are app functionality, not tracking. Flow requests omit the install ID, so no session data is recorded server-side.
- No attribution or conversion network requests are made
When re-enabled, attribution and conversion tracking resume for future events only. No backfill — data from while tracking was disabled is permanently gone.
Best Practices#
- Ask once, respect always: Don't repeatedly ask users who declined. Show a toggle in settings instead.
- Be clear about purpose: Explain that tracking helps you understand which ads work, not track their personal behavior.
- Offer granular control: Some users may be comfortable with attribution but not flow analytics.
- Document your compliance: Keep records of your consent implementation for audits.
AI agents: for complete Mobana SDK & API documentation, get full context here or visit llms.txt