Documentation Index Fetch the complete documentation index at: https://docs.datalyr.com/llms.txt
Use this file to discover all available pages before exploring further.
DATALYR provides native SDKs for iOS (Swift) and React Native, enabling mobile app tracking with attribution, SKAdNetwork support, and offline queuing.
What It Does
Mobile App Tracking:
iOS SDK (Swift) for native Apple apps
React Native SDK for cross-platform apps
Automatic session tracking
Attribution tracking (App Store, organic)
SKAdNetwork conversion value encoding
Offline event queue
App lifecycle tracking
iOS SDK (Swift)
Installation
Swift Package Manager:
Xcode:
File → Add Packages
Enter: https://github.com/datalyr/swift
Select version: 1.0.0+
Package.swift:
dependencies : [
. package ( url : "https://github.com/datalyr/swift" , from : "1.3.0" )
]
Basic Usage
Initialize SDK:
import DatalyrSDK
// In AppDelegate or App struct
try await DatalyrSDK. shared . initialize ( config : DatalyrConfig (
workspaceId : "your_workspace_id" ,
apiKey : "dk_your_api_key" ,
debug : true
))
Track Events:
// Track custom event
await DatalyrSDK. shared . track ( "button_tap" , eventData : [
"button_name" : "signup" ,
"screen" : "onboarding"
])
// Track with revenue
await DatalyrSDK. shared . track ( "purchase" , eventData : [
"revenue" : 99.99 ,
"currency" : "USD" ,
"product_id" : "prod_123"
])
Identify Users:
// After login
await DatalyrSDK. shared . identify ( "user_123" , properties : [
"email" : "[email protected] " ,
"name" : "John Doe" ,
"plan" : "pro"
])
Track Screens:
// Track screen view
await DatalyrSDK. shared . screen ( "Home Screen" , properties : [
"tab" : "feed"
])
Reset on Logout:
// Clear user identity
await DatalyrSDK. shared . reset ()
Configuration Options
let config = DatalyrConfig (
workspaceId : "your_workspace_id" ,
apiKey : "dk_your_api_key" ,
debug : false ,
endpoint : "https://ingest.datalyr.com/track" ,
// Queue settings
maxRetries : 3 ,
retryDelay : 1000 ,
timeout : 15000 ,
batchSize : 10 ,
flushInterval : 30000 ,
maxQueueSize : 100 ,
// Privacy
respectDoNotTrack : true ,
// Auto-events
enableAutoEvents : true ,
enableAttribution : true ,
// SKAdNetwork
skadTemplate : "ecommerce" // or "gaming", "subscription"
)
SKAdNetwork Support
Initialize with SKAdNetwork:
// Use template for automatic conversion value encoding
try await DatalyrSDK. initializeWithSKAdNetwork (
config : config,
template : "ecommerce"
)
Track with Automatic Encoding:
// Automatically updates SKAdNetwork conversion value
await DatalyrSDK. trackWithSKAdNetwork ( "purchase" , eventData : [
"revenue" : 99.99 ,
"currency" : "USD"
])
// Convenience method for purchases
await DatalyrSDK. trackPurchase (
value : 99.99 ,
currency : "USD" ,
productId : "prod_123"
)
// Convenience method for subscriptions
await DatalyrSDK. trackSubscription (
value : 9.99 ,
currency : "USD" ,
plan : "monthly"
)
Test Conversion Values:
// Get conversion value without sending to Apple
let value = DatalyrSDK. getConversionValue (
for : "purchase" ,
properties : [ "revenue" : 99.99 ]
)
print ( "Conversion value: \( value ?? 0 ) " )
Available Templates:
"ecommerce": Revenue-based encoding (0-6 brackets)
"gaming": Level progression and IAP
"subscription": Trial, active, churned states
Auto-Events
Automatically Tracked:
app_install: First launch
app_open: App foreground
app_close: App background
session_start: New session
session_end: Session timeout
Enable/Disable:
let config = DatalyrConfig (
workspaceId : "your_workspace_id" ,
apiKey : "dk_your_api_key" ,
enableAutoEvents : false // Disable auto-events
)
Attribution
Automatic Attribution:
SDK captures attribution data on install:
App Store referrer
Campaign parameters
Install timestamp
Get Attribution Data:
let attribution = DatalyrSDK. shared . getAttributionData ()
print ( "Attribution source: \( attribution. source ?? "unknown" ) " )
Set Attribution Manually:
await DatalyrSDK. shared . setAttributionData ( AttributionData (
source : "facebook" ,
medium : "cpc" ,
campaign : "summer_sale"
))
Session Management
Get Session Info:
// Current session ID
let sessionId = DatalyrSDK. shared . getStatus (). sessionId
// Current session data
let session = DatalyrSDK. shared . getCurrentSession ()
Manual Session Control:
// End session manually
await DatalyrSDK. shared . endSession ()
Advanced Features
Flush Manually:
// Flush queued events immediately
await DatalyrSDK. shared . flush ()
Get SDK Status:
let status = DatalyrSDK. shared . getStatus ()
print ( "Initialized: \( status. initialized ) " )
print ( "Visitor ID: \( status. visitorId ) " )
print ( "Queue size: \( status. queueStats . queueSize ) " )
Get Anonymous ID:
let anonId = DatalyrSDK. shared . getAnonymousId ()
Track Revenue Events:
await DatalyrSDK. shared . trackRevenue ( "subscription_renewal" , properties : [
"value" : 9.99 ,
"currency" : "USD" ,
"plan" : "monthly"
])
SwiftUI Integration
import SwiftUI
import DatalyrSDK
@main
struct MyApp : App {
init () {
Task {
try await DatalyrSDK. shared . initialize ( config : DatalyrConfig (
workspaceId : "your_workspace_id" ,
apiKey : "dk_your_api_key"
))
}
}
var body: some Scene {
WindowGroup {
ContentView ()
}
}
}
struct ContentView : View {
var body: some View {
Button ( "Track Event" ) {
Task {
await DatalyrSDK. shared . track ( "button_tap" )
}
}
}
}
React Native SDK
Installation
npm install @datalyr/react-native
Requirements:
React Native 0.60+
iOS 13+ / Android 5.0+
Basic Usage
Initialize SDK:
import { Datalyr } from '@datalyr/react-native' ;
// In App.tsx or index.js
await Datalyr . initialize ({
workspaceId: 'your_workspace_id' ,
apiKey: 'dk_your_api_key' ,
debug: true
});
Track Events:
// Track custom event
await Datalyr . track ( 'button_tap' , {
button_name: 'signup' ,
screen: 'onboarding'
});
// Track with revenue
await Datalyr . track ( 'purchase' , {
revenue: 99.99 ,
currency: 'USD' ,
product_id: 'prod_123'
});
Identify Users:
// After login
await Datalyr . identify ( 'user_123' , {
email: '[email protected] ' ,
name: 'John Doe' ,
plan: 'pro'
});
Track Screens:
// Track screen view
await Datalyr . screen ( 'HomeScreen' , {
tab: 'feed'
});
Reset on Logout:
// Clear user identity
await Datalyr . reset ();
Configuration Options
await Datalyr . initialize ({
workspaceId: 'your_workspace_id' ,
apiKey: 'dk_your_api_key' ,
debug: false ,
endpoint: 'https://ingest.datalyr.com/track' ,
// Queue settings
maxRetries: 3 ,
retryDelay: 1000 ,
timeout: 15000 ,
batchSize: 10 ,
flushInterval: 30000 ,
maxQueueSize: 100 ,
// Privacy
respectDoNotTrack: true ,
// Auto-events
enableAutoEvents: true ,
enableAttribution: true ,
// SKAdNetwork (iOS only)
skadTemplate: 'ecommerce'
});
SKAdNetwork Support (iOS)
Track with Automatic Encoding:
// Automatically updates SKAdNetwork conversion value (iOS only)
await Datalyr . trackWithSKAdNetwork ( 'purchase' , {
revenue: 99.99 ,
currency: 'USD'
});
// Convenience method for purchases
await Datalyr . trackPurchase ( 99.99 , 'USD' , 'prod_123' );
// Convenience method for subscriptions
await Datalyr . trackSubscription ( 9.99 , 'USD' , 'monthly' );
Test Conversion Values:
// Get conversion value without sending to Apple
const value = Datalyr . getConversionValue ( 'purchase' , { revenue: 99.99 });
console . log ( 'Conversion value:' , value );
Auto-Events
Automatically Tracked:
app_install: First launch
app_open: App foreground
app_close: App background
session_start: New session
session_end: Session timeout
Configuration:
await Datalyr . initialize ({
workspaceId: 'your_workspace_id' ,
apiKey: 'dk_your_api_key' ,
enableAutoEvents: true ,
autoEventConfig: {
trackAppLifecycle: true ,
trackScreenViews: true ,
trackDeepLinks: true ,
sessionTimeout: 1800000 // 30 minutes
}
});
Attribution
Get Attribution Data:
const attribution = Datalyr . getAttributionData ();
console . log ( 'Attribution source:' , attribution . source );
Set Attribution Manually:
await Datalyr . setAttributionData ({
source: 'facebook' ,
medium: 'cpc' ,
campaign: 'summer_sale'
});
Session Management
Get Session Info:
const status = Datalyr . getStatus ();
console . log ( 'Session ID:' , status . sessionId );
const session = Datalyr . getCurrentSession ();
console . log ( 'Session started:' , session . startTime );
Manual Session Control:
// End session manually
await Datalyr . endSession ();
Advanced Features
Flush Manually:
// Flush queued events immediately
await Datalyr . flush ();
Get SDK Status:
const status = Datalyr . getStatus ();
console . log ( 'Initialized:' , status . initialized );
console . log ( 'Visitor ID:' , status . visitorId );
console . log ( 'Queue size:' , status . queueStats . queueSize );
Get Anonymous ID:
const anonId = Datalyr . getAnonymousId ();
Alias User:
// Connect anonymous user to known user
await Datalyr . alias ( 'user_123' , 'previous_id' );
React Navigation Integration
import { NavigationContainer } from '@react-navigation/native' ;
import { Datalyr } from '@datalyr/react-native' ;
function App () {
const navigationRef = useRef ();
const routeNameRef = useRef ();
return (
< NavigationContainer
ref = { navigationRef }
onReady = { () => {
routeNameRef . current = navigationRef . current . getCurrentRoute (). name ;
} }
onStateChange = {async () => {
const previousRouteName = routeNameRef . current ;
const currentRouteName = navigationRef . current . getCurrentRoute (). name ;
if ( previousRouteName !== currentRouteName ) {
// Track screen view
await Datalyr . screen ( currentRouteName );
}
routeNameRef . current = currentRouteName ;
} }
>
< Stack.Navigator >
< Stack.Screen name = "Home" component = { HomeScreen } />
< Stack.Screen name = "Profile" component = { ProfileScreen } />
</ Stack.Navigator >
</ NavigationContainer >
);
}
TypeScript Support
Full TypeScript definitions included:
import { Datalyr , DatalyrConfig , EventData } from '@datalyr/react-native' ;
const config : DatalyrConfig = {
workspaceId: 'your_workspace_id' ,
apiKey: 'dk_your_api_key' ,
debug: true
};
await Datalyr . initialize ( config );
const eventData : EventData = {
revenue: 99.99 ,
currency: 'USD'
};
await Datalyr . track ( 'purchase' , eventData );
Revenue Tracking: SDK vs Webhooks
If you use Superwall or RevenueCat , do not use trackPurchase() or trackSubscription() for revenue attribution. These methods fire client-side before payment is confirmed, meaning trials and failed payments will be counted as revenue. Instead, use the Superwall or RevenueCat webhook integration — these send server-side events only when real money changes hands, with accurate revenue, trial status, and refund data.
With Superwall/RevenueCat (recommended for subscription apps):
Use the DATALYR SDK for behavioral events only : track('paywall_view'), track('trial_start'), screen(), identify(), etc.
Use the webhook integration for revenue events : purchases, renewals, cancellations, refunds
Pass attribution to Superwall/RevenueCat using getSuperwallAttributes() or getRevenueCatAttributes() so revenue events get linked back to the original campaign
Without Superwall/RevenueCat:
Use trackPurchase() and trackSubscription() only after confirming a real charge (not a trial start)
These methods are appropriate for one-time purchases or when you handle billing directly
Common Use Cases
E-commerce App
// Product view
await Datalyr . track ( 'product_view' , {
product_id: 'prod_123' ,
name: 'Premium Widget' ,
price: 99.99
});
// Add to cart
await Datalyr . track ( 'add_to_cart' , {
product_id: 'prod_123' ,
quantity: 2
});
// Purchase (with SKAdNetwork on iOS)
// Only use if NOT using Superwall/RevenueCat for revenue
await Datalyr . trackPurchase ( 199.98 , 'USD' , 'prod_123' );
Subscription App (with Superwall/RevenueCat)
// Use SDK for behavioral events
await Datalyr . track ( 'paywall_view' , { paywall_id: 'main' });
await Datalyr . track ( 'trial_start' , { plan: 'pro' , duration: 14 });
// Pass attribution to Superwall/RevenueCat
const attrs = Datalyr . getSuperwallAttributes (); // or getRevenueCatAttributes()
Superwall . setUserAttributes ( attrs );
// Revenue is tracked automatically via webhooks — don't call trackPurchase()
Subscription App (without Superwall/RevenueCat)
// Trial start — no revenue, so just track the event
await Datalyr . track ( 'trial_start' , {
plan: 'pro' ,
duration: 14
});
// Only track revenue after confirming a real charge
await Datalyr . trackSubscription ( 9.99 , 'USD' , 'monthly' );
// Subscription cancel
await Datalyr . track ( 'subscription_cancel' , {
plan: 'monthly' ,
reason: 'too_expensive'
});
Gaming App
// Level complete
await Datalyr . trackWithSKAdNetwork ( 'level_complete' , {
level: 5 ,
score: 1250 ,
time: 180
});
// In-app purchase
await Datalyr . trackPurchase ( 4.99 , 'USD' , 'coins_1000' );
// Achievement unlocked
await Datalyr . track ( 'achievement' , {
achievement_id: 'first_win' ,
points: 100
});
Best Practices
Initialize Early:
Initialize SDK in AppDelegate (iOS) or index.js (React Native) before any events.
Flush Before Exit:
SDK automatically flushes on app background, but manually call flush() for critical events.
Handle Offline:
SDK queues events offline and sends when connection restored.
Test Conversion Values:
Use getConversionValue() to test SKAdNetwork encoding before production.
Privacy:
Enable respectDoNotTrack and collect user consent before tracking.
Migrating from AppsFlyer / Adjust
DATALYR provides similar functionality to AppsFlyer and Adjust with a simpler integration and bundled platform SDKs.
From AppsFlyer
// BEFORE: AppsFlyer
import appsFlyer from 'react-native-appsflyer' ;
appsFlyer . initSdk ({ devKey: 'YOUR_DEV_KEY' , appId: 'YOUR_APP_ID' });
appsFlyer . logEvent ( 'af_purchase' , { af_revenue: 99.99 , af_currency: 'USD' });
// AFTER: DATALYR
import { Datalyr } from '@datalyr/react-native' ;
await Datalyr . initialize ({ apiKey: 'dk_your_api_key' });
await Datalyr . trackPurchase ( 99.99 , 'USD' , 'product_id' );
From Adjust
// BEFORE: Adjust
import { Adjust , AdjustConfig , AdjustEvent } from 'react-native-adjust' ;
const config = new AdjustConfig ( 'YOUR_TOKEN' , AdjustConfig . EnvironmentProduction );
Adjust . create ( config );
const event = new AdjustEvent ( 'abc123' );
event . setRevenue ( 99.99 , 'USD' );
Adjust . trackEvent ( event );
// AFTER: DATALYR
import { Datalyr } from '@datalyr/react-native' ;
await Datalyr . initialize ({ apiKey: 'dk_your_api_key' });
await Datalyr . trackPurchase ( 99.99 , 'USD' );
Event Name Mapping
AppsFlyer Event Adjust Event DATALYR Method af_purchasePURCHASEtrackPurchase()af_add_to_cartADD_TO_CARTtrackAddToCart()af_initiated_checkoutINITIATE_CHECKOUTtrackInitiateCheckout()af_complete_registrationCOMPLETE_REGISTRATIONtrackCompleteRegistration()af_content_viewVIEW_CONTENTtrackViewContent()af_searchSEARCHtrackSearch()af_subscribeSUBSCRIBEtrackSubscription()
Migration Benefits
No Ad SDKs Required: Uses native Apple and Google frameworks for IDFA and GAID
Unified API: Single SDK for all platforms and ad networks
Web-to-App: Automatic attribution matching via email
Flat Pricing: No per-MAU charges
Troubleshooting
Events Not Appearing
Check SDK Status:
const status = Datalyr . getStatus ();
console . log ( 'Initialized:' , status . initialized );
console . log ( 'Queue size:' , status . queueStats . queueSize );
Enable Debug Mode:
await Datalyr . initialize ({
apiKey: 'dk_your_api_key' ,
debug: true ,
});
Force Flush Events:
Verify API Key:
Should start with dk_
Check Settings → API Keys in dashboard
iOS Build Errors
cd ios
pod deintegrate
pod cache clean --all
pod install
Android Build Errors
cd android && ./gradlew clean
npx react-native run-android
Attribution Not Captured
Enable attribution in config:
await Datalyr . initialize ({
apiKey: 'dk_your_api_key' ,
enableAttribution: true ,
});
Check data:
const attribution = Datalyr . getAttributionData ();
console . log ( attribution );
SKAdNetwork Not Working
iOS 14.0+ required (iOS 16.1+ for SKAN 4.0)
Set skadTemplate in config
Use trackWithSKAdNetwork() for automatic encoding
Test with getConversionValue() first
App Tracking Transparency (iOS 14.5+)
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency' ;
const { status } = await requestTrackingPermissionsAsync ();
await Datalyr . updateTrackingAuthorization ( status === 'granted' );
Third-Party Integrations
Superwall
Push DATALYR attribution data into Superwall user attributes:
React Native:
import { Datalyr } from '@datalyr/react-native' ;
const attrs = Datalyr . getSuperwallAttributes ();
// Pass to Superwall
Superwall . setUserAttributes ( attrs );
iOS Swift:
let attrs = DatalyrSDK. shared . getSuperwallAttributes ()
Superwall. shared . setUserAttributes (attrs)
Returned attributes:
Key Description datalyr_idDATALYR visitor ID media_sourceAttribution source campaignCampaign name adgroupAd group or UTM content adAd ID keywordSearch keyword utm_sourceUTM source utm_mediumUTM medium utm_campaignUTM campaign fbclidFacebook click ID gclidGoogle click ID ttclidTikTok click ID idfaiOS advertising ID gaidGoogle advertising ID att_statusATT authorization status
RevenueCat
Push DATALYR attribution data into RevenueCat subscriber attributes:
React Native:
import { Datalyr } from '@datalyr/react-native' ;
import Purchases from 'react-native-purchases' ;
const attrs = Datalyr . getRevenueCatAttributes ();
Purchases . setAttributes ( attrs );
iOS Swift:
let attrs = DatalyrSDK. shared . getRevenueCatAttributes ()
Purchases. shared . attribution . setAttributes (attrs)
Returned attributes:
Key Description $datalyrIdDATALYR visitor ID $mediaSourceAttribution source $campaignCampaign name $adGroupAd group $adAd ID $keywordSearch keyword $idfaiOS advertising ID $gpsAdIdGoogle advertising ID $attConsentStatusATT consent status utm_sourceUTM source utm_mediumUTM medium utm_campaignUTM campaign fbclidFacebook click ID gclidGoogle click ID ttclidTikTok click ID
Learn more about Superwall integration
Learn more about RevenueCat integration
iOS SDK:
iOS 13.0+
Xcode 14+
Swift 5.5+
React Native SDK:
React Native 0.60+
iOS 13+ / Android 5.0+
Node.js 14+
Next Steps
Web SDK Browser tracking guide
Server SDK Backend tracking guide
Advanced Topics Identity, batching, plugins
Attribution Reports View attribution data