@datalyr/react-native
v1.7.5
Published
Datalyr SDK for React Native & Expo - Server-side attribution tracking for iOS and Android
Maintainers
Keywords
Readme
@datalyr/react-native
Mobile analytics and attribution SDK for React Native and Expo. Track events, identify users, and capture attribution data from ad platforms.
Table of Contents
- Installation
- Quick Start
- How It Works
- Configuration
- Event Tracking
- User Identity
- Sessions
- Attribution
- Customer Journey
- Event Queue
- Automatic Screen Tracking
- Auto Events
- SKAdNetwork
- Platform Integrations
- Enhanced App Campaigns
- Third-Party Integrations
- Migrating from AppsFlyer / Adjust
- Expo Support
- TypeScript
- API Reference
- Troubleshooting
- License
Installation
npm install @datalyr/react-nativeiOS Setup
cd ios && pod installAndroid Setup
No additional setup required.
Quick Start
import { Datalyr } from '@datalyr/react-native';
// Initialize
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
enableAutoEvents: true,
enableAttribution: true,
});
// Track events
await Datalyr.track('button_clicked', { button: 'signup' });
// Identify users
await Datalyr.identify('user_123', { email: '[email protected]' });
// Track purchases
await Datalyr.trackPurchase(99.99, 'USD', 'product_123');How It Works
The SDK collects events and sends them to the Datalyr backend for analytics and attribution.
Data Flow
- Events are created with
track(),screen(), or e-commerce methods - Each event includes device info, session data, and attribution parameters
- Events are queued locally and sent in batches
- If offline, events are stored and sent when connectivity returns
- Events are processed server-side for analytics and attribution reporting
Event Payload
Every event includes:
{
event: 'purchase', // Event name
properties: { ... }, // Custom properties
// Identity
anonymous_id: 'uuid', // Persistent device ID
user_id: 'user_123', // Set after identify()
session_id: 'uuid', // Current session
// Device
platform: 'ios',
device_model: 'iPhone 14',
os_version: '17.0',
app_version: '1.2.0',
// Attribution (if captured)
utm_source: 'facebook',
fbclid: 'abc123',
// Timestamps
timestamp: '2024-01-15T10:30:00Z',
}Configuration
All fields except apiKey are optional.
await Datalyr.initialize({
// Required
apiKey: string, // API key from dashboard (starts with 'dk_')
// Optional: workspace
workspaceId?: string, // Workspace ID for multi-workspace setups
// Debugging
debug?: boolean, // Console logging (default: false)
// Network
endpoint?: string, // API endpoint URL (default: 'https://ingest.datalyr.com/track')
useServerTracking?: boolean, // Use server-side tracking (default: true)
maxRetries?: number, // Max retry attempts for failed requests (default: 3)
retryDelay?: number, // Delay between retries in ms (default: 1000)
timeout?: number, // Request timeout in ms (default: 15000)
// Features
enableAutoEvents?: boolean, // Track app lifecycle automatically (default: true)
enableAttribution?: boolean, // Capture attribution data (default: true)
enableWebToAppAttribution?: boolean, // Web-to-app attribution matching (default: true)
// Event queue
batchSize?: number, // Events per batch (default: 10)
flushInterval?: number, // Auto-flush interval in ms (default: 30000)
maxQueueSize?: number, // Max queued events (default: 100)
// Auto events
autoEventConfig?: AutoEventConfig, // Fine-grained auto-event settings (see below)
// iOS
skadTemplate?: 'ecommerce' | 'gaming' | 'subscription', // SKAdNetwork conversion template
});AutoEventConfig
interface AutoEventConfig {
trackSessions?: boolean; // Track session_start / session_end (default: true)
trackScreenViews?: boolean; // Enable screen view events via screen() (default: true)
trackAppInstall?: boolean; // Track app_install on first open (default: true)
sessionTimeoutMs?: number; // Session timeout in ms
}Update at runtime:
Datalyr.updateAutoEventsConfig({
trackSessions: true,
sessionTimeoutMs: 1800000, // 30 minutes
});Event Tracking
Custom Events
// Simple event
await Datalyr.track('signup_started');
// Event with properties
await Datalyr.track('product_viewed', {
product_id: 'SKU123',
product_name: 'Blue Shirt',
price: 29.99,
currency: 'USD',
category: 'Apparel',
});
// Event with value
await Datalyr.track('level_completed', {
level: 5,
score: 1250,
time_seconds: 120,
});Screen Views
await Datalyr.screen('Home');
await Datalyr.screen('Product Details', {
product_id: 'SKU123',
source: 'search',
});Each screen() call fires a single pageview event with the screen property set. Session data (session_id, pageviews_in_session, previous_screen) is automatically attached.
E-Commerce Events
Standard e-commerce events:
// View product
await Datalyr.trackViewContent('SKU123', 'Blue Shirt', 'product', 29.99, 'USD');
// Add to cart
await Datalyr.trackAddToCart(29.99, 'USD', 'SKU123', 'Blue Shirt');
// Start checkout
await Datalyr.trackInitiateCheckout(59.98, 'USD', 2, ['SKU123', 'SKU456']);
// Complete purchase
await Datalyr.trackPurchase(59.98, 'USD', 'order_123');
// Subscription
await Datalyr.trackSubscription(9.99, 'USD', 'monthly_pro');
// Registration
await Datalyr.trackCompleteRegistration('email');
// Search
await Datalyr.trackSearch('blue shoes', ['SKU1', 'SKU2']);
// Lead
await Datalyr.trackLead(100.0, 'USD');
// Payment info
await Datalyr.trackAddPaymentInfo(true);Revenue Events
Important: If you use Superwall or RevenueCat, do not track revenue client-side. Use the Superwall or RevenueCat webhook integration instead — they only fire when real money changes hands. Use the SDK for behavioral events only (
track('paywall_view'),track('trial_start'),screen(),identify(), etc.).
User Identity
Anonymous ID
Every device gets a persistent anonymous ID on first launch:
const anonymousId = Datalyr.getAnonymousId();
// 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'This ID:
- Persists across app sessions
- Links events before and after user identification
- Can be passed to your backend for server-side attribution
Identifying Users
Link the anonymous ID to a known user:
await Datalyr.identify('user_123', {
email: '[email protected]',
});After identify():
- All future events include
user_id - Historical anonymous events can be linked server-side
Alias
Associate a new user ID with a previous one. Use this when a user's identity changes (e.g., after account merge):
// Link new ID to the currently identified user
await Datalyr.alias('new_user_456');
// Or specify the previous ID explicitly
await Datalyr.alias('new_user_456', 'old_user_123');User Properties
Pass any user attributes:
await Datalyr.identify('user_123', {
// Standard fields
email: '[email protected]',
name: 'John Doe',
phone: '+1234567890',
// Custom fields
plan: 'premium',
company: 'Acme Inc',
signup_date: '2024-01-15',
});Logout
Clear user data on logout:
await Datalyr.reset();This:
- Clears the user ID
- Starts a new session
- Keeps the anonymous ID (same device)
Sessions
// Get current session data
const session = Datalyr.getCurrentSession();
// Force end the current session
await Datalyr.endSession();Sessions are managed automatically when enableAutoEvents is enabled. A new session starts on app launch, and the current session ends after 30 minutes of inactivity (configurable via autoEventConfig.sessionTimeoutMs).
Attribution
Automatic Capture
The SDK captures attribution from deep links and referrers:
const attribution = Datalyr.getAttributionData();Captured parameters:
| Type | Parameters |
|------|------------|
| UTM | utm_source, utm_medium, utm_campaign, utm_content, utm_term |
| Click IDs | fbclid, gclid, ttclid, twclid, li_click_id, msclkid |
| Campaign | campaign_id, adset_id, ad_id |
Manual Attribution
Set attribution programmatically:
await Datalyr.setAttributionData({
utm_source: 'newsletter',
utm_campaign: 'spring_sale',
});Web-to-App Attribution
Automatically recover attribution from a web prelander when users install the app from an ad.
How it works:
- Android: Attribution params are passed through the Play Store
referrerURL parameter (set by the web SDK'strackAppDownloadClick()). The mobile SDK reads these via the Play Install Referrer API -- deterministic, ~95% accuracy. - iOS: On first install, the SDK calls the Datalyr API to match the device's IP against recent
$app_download_clickweb events within 24 hours -- ~90%+ accuracy for immediate installs.
No additional mobile code is needed. Attribution is recovered automatically during initialize() on first install, before the app_install event fires.
After a match, the SDK:
- Merges web attribution (click IDs, UTMs, cookies) into the mobile session
- Tracks a
$web_attribution_matchedevent for analytics - All subsequent events (including purchases) carry the matched attribution
Fallback: If IP matching misses (e.g., VPN toggle during install), email-based attribution is still recovered when identify() is called with the user's email.
Deferred Attribution
Retrieve deferred attribution data captured from deep links or install referrers:
const deferred = Datalyr.getDeferredAttributionData();
if (deferred) {
console.log(deferred.url); // Deep link URL
console.log(deferred.source); // Attribution source
console.log(deferred.fbclid); // Facebook click ID
console.log(deferred.gclid); // Google click ID
console.log(deferred.ttclid); // TikTok click ID
console.log(deferred.utmSource); // UTM source
console.log(deferred.utmMedium); // UTM medium
console.log(deferred.utmCampaign); // UTM campaign
console.log(deferred.utmContent); // UTM content
console.log(deferred.utmTerm); // UTM term
console.log(deferred.campaignId); // Campaign ID
console.log(deferred.adsetId); // Adset ID
console.log(deferred.adId); // Ad ID
}Customer Journey
Access multi-touch attribution journey data via the datalyr singleton instance:
import { datalyr } from '@datalyr/react-native';
// Summary: first/last touch, touchpoint count
const summary = datalyr.getJourneySummary();
// Full journey: all touchpoints in order
const journey = datalyr.getJourney();Event Queue
Events are batched for efficiency and offline support.
Configuration
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
batchSize: 10, // Send when 10 events queued
flushInterval: 30000, // Or every 30 seconds
maxQueueSize: 100, // Max events to store offline
});Manual Flush
Send all queued events immediately:
await Datalyr.flush();Queue Status
const status = Datalyr.getStatus();
console.log(status.queueStats.queueSize); // Events waiting
console.log(status.queueStats.pending); // Events being sentOffline Support
When the device is offline:
- Events are stored locally
- Queue persists across app restarts
- Events are sent when connectivity returns
Automatic Screen Tracking
Track screen views automatically when using React Navigation (v5+/v6+). The datalyrScreenTracking helper wires into the navigation container and fires a pageview event on every route change.
React Navigation
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import { datalyrScreenTracking } from '@datalyr/react-native';
function App() {
const navigationRef = useNavigationContainerRef();
const screenTracking = datalyrScreenTracking(navigationRef);
return (
<NavigationContainer
ref={navigationRef}
onReady={screenTracking.onReady}
onStateChange={screenTracking.onStateChange}
>
{/* ...screens */}
</NavigationContainer>
);
}Expo with React Navigation
For Expo projects using React Navigation, import from the Expo entry point:
import { datalyrScreenTracking } from '@datalyr/react-native/expo';The API is identical to the React Navigation example above.
Expo Router
For Expo Router apps, use the useDatalyrScreenTracking hook in your root layout. It automatically tracks every route change as a pageview event:
// app/_layout.tsx
import { useDatalyrScreenTracking } from '@datalyr/react-native/expo';
import { Stack } from 'expo-router';
export default function RootLayout() {
useDatalyrScreenTracking();
return <Stack />;
}Screen names are raw pathnames (e.g. /onboarding/paywall, /(app)/chat). You can map specific paths to friendly names:
useDatalyrScreenTracking({
screenNames: {
'/onboarding/paywall': 'Paywall',
'/(app)/chat': 'Chat',
},
});Additional options:
useDatalyrScreenTracking({
// Map specific paths to friendly names (checked first)
screenNames: { '/': 'Home' },
// Transform all other pathnames (e.g. strip route groups)
transformPathname: (path) => path.replace(/\(.*?\)\//g, ''),
// Skip tracking for certain paths
shouldTrackPath: (path) => !path.startsWith('/modal'),
});Configuration
You can customize screen name transforms, filtering, and property extraction:
const screenTracking = datalyrScreenTracking(navigationRef, {
// Clean up route names
transformScreenName: (name) => name.replace('Screen', ''),
// Skip certain screens
shouldTrackScreen: (name) => !['Splash', 'Loading'].includes(name),
// Extract route params as event properties
extractProperties: (name, params) => ({
product_id: params?.productId,
}),
});Advanced: Custom Tracking Function
If you need to control which SDK instance is used, use createScreenTrackingListeners instead:
import { createScreenTrackingListeners } from '@datalyr/react-native';
const { onReady, onStateChange } = createScreenTrackingListeners(
navigationRef,
(screenName, properties) => myCustomSdk.screen(screenName, properties),
);Note: If you enable automatic screen tracking, avoid also calling
Datalyr.screen()manually for the same screens, as this will produce duplicate events.
Auto Events
Enable automatic lifecycle tracking:
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
enableAutoEvents: true,
});| Event | Trigger |
|-------|---------|
| app_install | First app open |
| session_start | New session begins |
| session_end | Session expires (30 min inactivity) |
SKAdNetwork
iOS conversion tracking with Apple's SKAdNetwork:
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
skadTemplate: 'ecommerce',
});
// Track with automatic SKAN conversion value encoding
await Datalyr.trackWithSKAdNetwork('purchase', { value: 99.99 });
// Or use e-commerce helpers (also update SKAN automatically)
await Datalyr.trackPurchase(99.99, 'USD');| Template | Events |
|----------|--------|
| ecommerce | purchase, add_to_cart, begin_checkout, signup, subscribe, view_item |
| gaming | level_complete, tutorial_complete, purchase, achievement_unlocked |
| subscription | trial_start, subscribe, upgrade, cancel, signup |
Test Conversion Values
Preview the conversion value an event would produce without sending it to Apple:
const value = Datalyr.getConversionValue('purchase', { value: 49.99 });
// Returns a number (0-63) or null if no template is configuredPlatform Integrations
Conversion events are routed to ad platforms server-side via the Datalyr postback system. No client-side ad SDKs (Facebook SDK, TikTok SDK, etc.) are needed in your app. The SDK captures click IDs and attribution data from ad URLs, then the backend handles hashing, formatting, and sending conversions to each platform's API.
Meta (Facebook)
Conversions are sent to Meta via the Conversions API (CAPI).
What the SDK does: Captures fbclid from ad click URLs, collects IDFA (when ATT authorized on iOS), and sends user data (email, phone) with events.
What the backend does: Hashes PII (SHA-256), formats the CAPI payload, and sends conversions with the fbclid and _fbc/_fbp cookies for matching.
Setup:
- Connect your Meta ad account in the Datalyr dashboard (Settings > Connections)
- Select your Meta Pixel
- Create postback rules to map events (e.g.,
purchase->Purchase,lead->Lead)
No Facebook SDK needed in your app. No Info.plist changes, no FacebookAppID.
TikTok
Conversions are sent to TikTok via the Events API.
What the SDK does: Captures ttclid from ad click URLs and collects device identifiers (IDFA on iOS, GAID on Android).
What the backend does: Hashes user data, formats the Events API payload, and sends conversions with the ttclid and _ttp cookie for matching.
Setup:
- Connect your TikTok Ads account in the Datalyr dashboard (Settings > Connections)
- Select your TikTok Pixel
- Create postback rules to map events (e.g.,
purchase->CompletePayment,add_to_cart->AddToCart)
No TikTok SDK needed in your app. No access tokens, no native configuration.
Google Ads
Conversions are sent to Google via the Google Ads API.
What the SDK does: Captures gclid, gbraid, and wbraid from ad click URLs. Collects user data for enhanced conversions.
What the backend does: Hashes user data, maps events to Google conversion actions, and sends conversions with click IDs for attribution.
Setup:
- Connect your Google Ads account in the Datalyr dashboard (Settings > Connections)
- Select your conversion actions
- Create postback rules to map events (e.g.,
purchase-> your Google conversion action)
No Google SDK needed in your app beyond the Play Install Referrer (already included for Android).
Apple Search Ads
Attribution for users who install from Apple Search Ads (iOS 14.3+). Automatically fetched on initialization.
// Check if user came from Apple Search Ads
const asaAttribution = Datalyr.getAppleSearchAdsAttribution();
if (asaAttribution?.attribution) {
console.log(asaAttribution.campaignId); // Campaign ID
console.log(asaAttribution.campaignName); // Campaign name
console.log(asaAttribution.adGroupId); // Ad group ID
console.log(asaAttribution.keyword); // Search keyword
console.log(asaAttribution.clickDate); // Click date
}Attribution data is automatically included in all events with the asa_ prefix:
asa_campaign_id,asa_campaign_nameasa_ad_group_id,asa_ad_group_nameasa_keyword_id,asa_keywordasa_org_id,asa_org_nameasa_click_date,asa_conversion_type
No additional configuration needed. The SDK uses Apple's AdServices API.
Google Play Install Referrer
Android-only. Captures UTM parameters and click IDs from the Google Play Store install referrer URL. This data is retrieved automatically on first launch via the Play Install Referrer API.
How it works:
- User clicks an ad or link with UTM parameters
- Google Play Store stores the referrer URL
- On first app launch, the SDK retrieves the referrer
- Attribution data (utm_source, utm_medium, gclid, etc.) is extracted and merged into the session
Access the raw referrer data:
import { datalyr } from '@datalyr/react-native';
const referrer = datalyr.getPlayInstallReferrer();
if (referrer) {
// Google Ads click IDs
console.log(referrer.gclid); // Standard Google Ads click ID
console.log(referrer.gbraid); // Privacy-safe click ID (iOS App campaigns)
console.log(referrer.wbraid); // Privacy-safe click ID (Web-to-App campaigns)
// UTM parameters
console.log(referrer.utmSource);
console.log(referrer.utmMedium);
console.log(referrer.utmCampaign);
console.log(referrer.utmTerm);
console.log(referrer.utmContent);
// Timestamps
console.log(referrer.referrerClickTimestamp); // When the referrer link was clicked (ms)
console.log(referrer.installBeginTimestamp); // When the install began (ms)
console.log(referrer.installCompleteTimestamp); // When the install completed (ms)
// Raw referrer URL
console.log(referrer.referrerUrl);
}Requirements:
- Android only (returns
nullon iOS) - Requires the Google Play Install Referrer Library in
android/app/build.gradle:implementation 'com.android.installreferrer:installreferrer:2.2'
App Tracking Transparency
Update after ATT dialog:
const { status } = await requestTrackingPermissionsAsync();
await Datalyr.updateTrackingAuthorization(status === 'granted');Integration Status
const status = Datalyr.getPlatformIntegrationStatus();
// { appleSearchAds: boolean, playInstallReferrer: boolean }Enhanced App Campaigns
Run mobile app ads through web campaigns (Meta Sales, TikTok Traffic, Google Ads) that redirect users to the app store through your own domain. This bypasses SKAN restrictions, ATT requirements, and adset limits -- ad platforms treat these as regular web campaigns.
How It Works
- User clicks your ad -> lands on a page on your domain with the Datalyr web SDK (
dl.js) - SDK captures attribution (fbclid, ttclid, gclid, UTMs, ad cookies like
_fbp/_fbc/_ttp) - User redirects to app store (via button click or auto-redirect)
- User installs app -> mobile SDK matches via Play Store referrer (Android, ~95%) or IP matching (iOS, ~90%+)
- In-app events fire -> conversions sent to Meta/TikTok/Google server-side via postbacks
Setup
1. Create a tracking link in the Datalyr dashboard: Track -> Create Link -> App Link. Enter your prelander page URL and app store URLs.
2. Host a page on your domain with one of these options:
Option A: Prelander (Recommended)
A real landing page with a download button. Better ad platform compliance, higher intent.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Download Your App</title>
<script src="https://track.datalyr.com/dl.js" data-workspace-id="YOUR_WORKSPACE_ID"></script>
</head>
<body>
<h1>Download Our App</h1>
<button id="ios-download">Download for iOS</button>
<button id="android-download">Download for Android</button>
<script>
document.getElementById('ios-download').addEventListener('click', function() {
Datalyr.trackAppDownloadClick({
targetPlatform: 'ios',
appStoreUrl: 'https://apps.apple.com/app/idXXXXXXXXXX'
});
});
document.getElementById('android-download').addEventListener('click', function() {
Datalyr.trackAppDownloadClick({
targetPlatform: 'android',
appStoreUrl: 'https://play.google.com/store/apps/details?id=com.example.app'
});
});
</script>
</body>
</html>Option B: Redirect Page
Instant redirect -- no visible content, user goes straight to app store.
Note: Some ad platforms (particularly Meta) may flag redirect pages with no visible content as low-quality landing pages or cloaking. Use the prelander option if compliance is a concern.
<!DOCTYPE html>
<html>
<head>
<script src="https://track.datalyr.com/dl.js" data-workspace-id="YOUR_WORKSPACE_ID"></script>
<script>
window.addEventListener('DOMContentLoaded', function() {
var isAndroid = /android/i.test(navigator.userAgent);
Datalyr.trackAppDownloadClick({
targetPlatform: isAndroid ? 'android' : 'ios',
appStoreUrl: isAndroid
? 'https://play.google.com/store/apps/details?id=com.example.app'
: 'https://apps.apple.com/app/idXXXXXXXXXX'
});
});
</script>
</head>
<body></body>
</html>3. Set up your ad campaign:
- Meta Ads: Campaign objective -> Sales, conversion location -> Website, placements -> Mobile only. Paste your page URL as the Website URL. No SKAN, no ATT, no adset limits.
- TikTok Ads: Campaign objective -> Website Conversions, paste your page URL as destination. Select your TikTok Pixel from Datalyr.
- Google Ads: Performance Max or Search campaign. Use your page URL as the landing page.
Add UTM parameters to the URL so attribution flows through:
- Meta:
?utm_source=facebook&utm_medium=cpc&utm_campaign={{campaign.name}}&utm_content={{adset.name}}&utm_term={{ad.name}} - TikTok:
?utm_source=tiktok&utm_medium=cpc&utm_campaign=__CAMPAIGN_NAME__&utm_content=__AID_NAME__&utm_term=__CID_NAME__ - Google:
?utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_content={adgroupid}&utm_term={keyword}
Important
- The page must load JavaScript. Server-side redirects (301/302, nginx, Cloudflare Page Rules) will NOT work.
- Host on your own domain -- do not use
datalyr.comor shared domains. - The redirect page adds ~100-200ms for the SDK to load. Prelander has no latency since the user clicks a button.
Third-Party Integrations
Superwall
Pass Datalyr attribution data to Superwall to personalize paywalls by ad source, campaign, ad set, and keyword.
import { Datalyr } from '@datalyr/react-native';
import Superwall from '@superwall/react-native-superwall';
// After both SDKs are initialized
Superwall.setUserAttributes(Datalyr.getSuperwallAttributes());
// Your placements will now have attribution data available as filters
Superwall.register({ placement: 'onboarding_paywall' });Call after Datalyr.initialize() completes. If using ATT on iOS, call again after the user responds to the ATT prompt to include the IDFA.
Returned attribute keys:
| Key | Description |
|-----|-------------|
| datalyr_id | The user's DATALYR visitor ID |
| media_source | Traffic source (e.g., facebook, google) |
| campaign | Campaign name from the ad |
| adgroup | Ad group or ad set name |
| ad | Individual ad ID |
| keyword | Search keyword that triggered the ad |
| network | Ad network name |
| utm_source | UTM source parameter |
| utm_medium | UTM medium parameter (e.g., cpc) |
| utm_campaign | UTM campaign parameter |
| utm_term | UTM term parameter |
| utm_content | UTM content parameter |
| lyr | DATALYR tracking link ID |
| fbclid | Meta click ID from the ad URL |
| gclid | Google click ID from the ad URL |
| ttclid | TikTok click ID from the ad URL |
| idfa | Apple advertising ID (only if ATT authorized) |
| gaid | Google advertising ID (Android) |
| att_status | App Tracking Transparency status (0-3) |
Only non-empty values are included.
RevenueCat
Pass Datalyr attribution data to RevenueCat for revenue attribution and offering targeting.
import { Datalyr } from '@datalyr/react-native';
import Purchases from 'react-native-purchases';
// After both SDKs are configured
Purchases.setAttributes(Datalyr.getRevenueCatAttributes());Call after configuring the Purchases SDK and before the first purchase. If using ATT, call again after permission is granted to include IDFA.
Reserved attributes ($-prefixed):
| Key | Description |
|-----|-------------|
| $datalyrId | The user's DATALYR visitor ID |
| $mediaSource | Traffic source (e.g., facebook, google) |
| $campaign | Campaign name from the ad |
| $adGroup | Ad group or ad set name |
| $ad | Individual ad ID |
| $keyword | Search keyword that triggered the ad |
| $idfa | Apple advertising ID (only if ATT authorized) |
| $gpsAdId | Google advertising ID (Android) |
| $attConsentStatus | ATT consent status (see mapping below) |
ATT status mapping for $attConsentStatus:
| ATT Value | String |
|-----------|--------|
| 0 | notDetermined |
| 1 | restricted |
| 2 | denied |
| 3 | authorized |
Custom attributes:
| Key | Description |
|-----|-------------|
| utm_source | UTM source parameter |
| utm_medium | UTM medium parameter (e.g., cpc) |
| utm_campaign | UTM campaign parameter |
| utm_term | UTM term parameter |
| utm_content | UTM content parameter |
| lyr | DATALYR tracking link ID |
| fbclid | Meta click ID from the ad URL |
| gclid | Google click ID from the ad URL |
| ttclid | TikTok click ID from the ad URL |
| wbraid | Google web-to-app click ID |
| gbraid | Google app click ID |
| network | Ad network |
| creative_id | Creative ID |
Only non-empty values are included.
Datalyr also receives Superwall and RevenueCat events via server-side webhooks for analytics. The SDK methods and webhook integration are independent -- you can use one or both.
Migrating from AppsFlyer / Adjust
Datalyr provides similar functionality with a simpler integration.
From AppsFlyer
// BEFORE: AppsFlyer
import appsFlyer from 'react-native-appsflyer';
appsFlyer.logEvent('af_purchase', { af_revenue: 99.99, af_currency: 'USD' });
// AFTER: Datalyr
import { Datalyr } from '@datalyr/react-native';
await Datalyr.trackPurchase(99.99, 'USD', 'product_id');From Adjust
// BEFORE: Adjust
import { Adjust, AdjustEvent } from 'react-native-adjust';
const event = new AdjustEvent('abc123');
event.setRevenue(99.99, 'USD');
Adjust.trackEvent(event);
// AFTER: Datalyr
import { Datalyr } from '@datalyr/react-native';
await Datalyr.trackPurchase(99.99, 'USD');Event Mapping
| AppsFlyer | Adjust | Datalyr |
|-----------|--------|---------|
| af_purchase | PURCHASE | trackPurchase() |
| af_add_to_cart | ADD_TO_CART | trackAddToCart() |
| af_initiated_checkout | INITIATE_CHECKOUT | trackInitiateCheckout() |
| af_complete_registration | COMPLETE_REGISTRATION | trackCompleteRegistration() |
| af_content_view | VIEW_CONTENT | trackViewContent() |
| af_subscribe | SUBSCRIBE | trackSubscription() |
Migration Checklist
- [ ] Remove old SDK:
npm uninstall react-native-appsflyer - [ ] Install Datalyr:
npm install @datalyr/react-native - [ ] Run
cd ios && pod install - [ ] Replace initialization and event tracking code
- [ ] Verify events in Datalyr dashboard
Expo Support
import { Datalyr } from '@datalyr/react-native/expo';Same API as standard React Native.
TypeScript
import {
Datalyr,
DatalyrConfig,
EventData,
UserProperties,
AttributionData,
AutoEventConfig,
DeferredDeepLinkResult,
} from '@datalyr/react-native';API Reference
All methods are static on the Datalyr class unless noted otherwise.
Initialization
| Method | Description |
|--------|-------------|
| initialize(config: DatalyrConfig) | Initialize the SDK. Must be called before any other method. |
Event Tracking
| Method | Description |
|--------|-------------|
| track(eventName, eventData?) | Track a custom event |
| screen(screenName, properties?) | Track a screen view |
| trackWithSKAdNetwork(event, properties?) | Track event with SKAN conversion value encoding |
| trackPurchase(value, currency?, productId?) | Track a purchase |
| trackSubscription(value, currency?, plan?) | Track a subscription |
| trackAddToCart(value, currency?, productId?, productName?) | Track add-to-cart |
| trackViewContent(contentId?, contentName?, contentType?, value?, currency?) | Track content view |
| trackInitiateCheckout(value, currency?, numItems?, productIds?) | Track checkout start |
| trackCompleteRegistration(method?) | Track registration |
| trackSearch(query, resultIds?) | Track a search |
| trackLead(value?, currency?) | Track a lead |
| trackAddPaymentInfo(success?) | Track payment info added |
User Identity
| Method | Description |
|--------|-------------|
| identify(userId, properties?) | Identify a user |
| alias(newUserId, previousId?) | Associate a new user ID with a previous one |
| reset() | Clear user ID and start new session |
| getAnonymousId() | Get the persistent anonymous device ID |
Sessions
| Method | Description |
|--------|-------------|
| getCurrentSession() | Get current session data |
| endSession() | Force end the current session |
Attribution
| Method | Description |
|--------|-------------|
| getAttributionData() | Get captured attribution data |
| setAttributionData(data) | Set attribution data manually |
| getDeferredAttributionData() | Get deferred attribution from deep links / install referrer |
Configuration
| Method | Description |
|--------|-------------|
| updateAutoEventsConfig(config) | Update auto-event settings at runtime |
Platform Integrations
| Method | Description |
|--------|-------------|
| getAppleSearchAdsAttribution() | Get Apple Search Ads attribution (iOS) |
| getPlatformIntegrationStatus() | Check which platform integrations are active |
| updateTrackingAuthorization(enabled) | Update ATT status after user responds to dialog |
SKAdNetwork
| Method | Description |
|--------|-------------|
| getConversionValue(event, properties?) | Preview conversion value without sending to Apple |
Third-Party Integrations
| Method | Description |
|--------|-------------|
| getSuperwallAttributes() | Get attribution formatted for Superwall |
| getRevenueCatAttributes() | Get attribution formatted for RevenueCat |
Status
| Method | Description |
|--------|-------------|
| getStatus() | Get SDK status (initialized, queue stats, online) |
| flush() | Send all queued events immediately |
Instance Methods (via datalyr singleton)
These methods are available on the datalyr instance export, not on the static Datalyr class:
import { datalyr } from '@datalyr/react-native';| Method | Description |
|--------|-------------|
| getJourneySummary() | Get journey summary (first/last touch, touchpoint count) |
| getJourney() | Get full customer journey (all touchpoints) |
| getPlayInstallReferrer() | Get raw Play Install Referrer data (Android) |
Troubleshooting
Events Not Appearing
1. Check SDK Status
const status = Datalyr.getStatus();
console.log('Initialized:', status.initialized);
console.log('Queue size:', status.queueStats.queueSize);
console.log('Online:', status.queueStats.isOnline);2. Enable Debug Mode
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
debug: true,
});3. Force Flush
await Datalyr.flush();4. Verify API Key - Should start with dk_
iOS Build Errors
cd ios
pod deintegrate
pod cache clean --all
pod installClean Reset
rm -rf node_modules ios/Pods ios/Podfile.lock
npm install && cd ios && pod installAndroid Build Errors
cd android && ./gradlew clean
npx react-native run-androidSKAdNetwork Not Updating
- iOS 14.0+ required (16.1+ for SKAN 4.0)
- Set
skadTemplatein config - Use
trackWithSKAdNetwork()instead oftrack()
Attribution Not Captured
await Datalyr.initialize({
apiKey: 'dk_your_api_key',
enableAttribution: true,
});
// Check data
const attribution = Datalyr.getAttributionData();App Tracking Transparency (iOS 14.5+)
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
const { status } = await requestTrackingPermissionsAsync();
await Datalyr.updateTrackingAuthorization(status === 'granted');Debug Logging
Look for [Datalyr] prefixed messages in console.
License
MIT
