@freshpaint/freshpaint-react-native
Freshpaint React Native SDK
Comprehensive analytics tracking SDK for React Native applications with advanced attribution, autotracking, and privacy features.
Documentation: Freshpaint React Native SDK Reference
Table of Contents
- Installation
- Quick Start
- Core Features
- MMP Attribution
- Autotracking
- Advanced Configuration
- API Reference
Installation
npm install @freshpaint/freshpaint-react-native
# or
yarn add @freshpaint/freshpaint-react-native
iOS Setup
cd ios && pod install
Add to your Info.plist if requesting ATT:
<key>NSUserTrackingUsageDescription</key>
<string>This app would like to track your activity for personalized ads and analytics.</string>
Android Setup
No additional setup required. The SDK automatically links native modules.
Quick Start
import Freshpaint from '@freshpaint/freshpaint-react-native';
// Initialize the SDK
Freshpaint.init('YOUR_API_KEY', {
autoRequestATT: true, // Automatically request ATT on iOS (optional)
});
// Track an event
Freshpaint.track('Product Viewed', {
product_id: '123',
product_name: 'Premium Widget',
price: 29.99,
});
// Identify a user
Freshpaint.identify('user_123', {
email: 'user@example.com',
plan: 'premium',
});
Core Features
Event Tracking
Track custom events with optional properties:
Freshpaint.track('Button Clicked', {
button_name: 'Sign Up',
screen: 'Home',
});
Integration Options
Send events to specific destinations:
Freshpaint.track(
'Purchase Completed',
{
total: 99.99,
items: 3,
},
{
integrations: {
'Google Analytics': true,
Mixpanel: false,
},
},
);
User Identification
Associate events with a specific user:
// Identify with user ID and properties
Freshpaint.identify('user_123', {
email: 'user@example.com',
name: 'John Doe',
plan: 'premium',
});
// Update user properties without changing ID
Freshpaint.identify({
last_login: new Date().toISOString(),
});
Integration Options for Identify
Freshpaint.identify(
'user_123',
{
email: 'user@example.com',
},
{
integrations: {
Salesforce: true,
Intercom: true,
},
},
);
Groups
Associate users with groups (teams, companies, etc.):
// Set group with properties
Freshpaint.group('company_456', {
name: 'Acme Corp',
plan: 'enterprise',
employees: 500,
});
// Update group properties without changing ID
Freshpaint.group({
subscription_status: 'active',
});
Integration Options for Group
Freshpaint.group(
'company_456',
{
name: 'Acme Corp',
},
{
integrations: {
Salesforce: true,
},
},
);
Custom Properties
Add custom properties to all events:
// Add properties (merged with existing)
Freshpaint.addEventProperties({
app_version: '2.1.0',
environment: 'production',
});
// Add properties with lower priority (won't override existing)
Freshpaint.addInitialEventProperties({
default_currency: 'USD',
});
// Remove a property
Freshpaint.removeEventProperty('environment');
Reset User State
Clear all user data (useful on logout):
Freshpaint.reset();
This clears:
- User ID
- User properties
- Group ID and properties
- Custom event properties
- Generates new device ID
MMP Attribution
The SDK provides comprehensive Mobile Measurement Partner (MMP) attribution capabilities with automatic data collection and event tracking.
App First Open
Automatically fires an Application Installed event on the first app launch with complete attribution data.
What's Collected:
Common (iOS & Android):
install_timestamp- ISO 8601 timestamp of first opendevice_id- Freshpaint device identifierpersistent_device_id- Survives app uninstall/reinstallos_version- OS version stringversion- App version from bundlebuild- App build numberuser_agent- User agent string- UTM parameters (
utm_source,utm_medium,utm_campaign,utm_term,utm_content) - 35 ad click IDs (see Deep Link Tracking for full list)
iOS:
idfv- Identifier for Vendor (always available)advertisingId- Advertising Identifier / IDFA (only if ATT authorized)att_status- ATT authorization status (authorized,denied,restricted,notDetermined)skan_registration_attempted- Boolean indicating SKAdNetwork registrationapple_ads_token- Apple Search Ads attribution token (iOS 14.3+, if available)
Android:
advertisingId- Google Advertising ID (GAID) - preferred identifierandroid_id- Android ID (fallback when GAID unavailable)limit_ad_tracking- Boolean indicating ad tracking preferenceinstall_referrer- Play Store install referrer stringreferrer_click_timestamp- Unix timestamp of ad clickinstall_begin_timestamp- Unix timestamp of install start
Google Policy Compliance: The SDK follows Google Play policy by never sending both GAID and
android_idin the same request. It prefers GAID and falls back toandroid_idonly when GAID is unavailable.
Example Payload:
{
event: 'Application Installed',
properties: {
custom_props: {
install_timestamp: '2024-01-15T10:30:00.000Z',
device_id: 'abc123...',
persistent_device_id: 'xyz789...',
os_version: '17.2',
version: '1.0.0',
build: '123',
user_agent: 'MyApp/1.0.0 (iPhone; iOS 17.2)',
// iOS-specific
idfv: '12345678-1234-1234-1234-123456789012',
advertisingId: '87654321-4321-4321-4321-210987654321', // if authorized
att_status: 'authorized',
skan_registration_attempted: true,
// Attribution params (if opened via deep link)
utm_source: 'facebook',
utm_campaign: 'summer_sale',
fbclid: 'abc123',
gclid: 'xyz456',
}
}
}
Deep Link Tracking
Automatically tracks deep link opens with full attribution parsing.
Events:
- Cold start (app not running): Fires
deeplinkevent with URL and parameters - Warm open (app backgrounded): Fires
deeplinkevent on foreground
Supported Attribution Parameters:
UTM Parameters (5):
utm_source,utm_medium,utm_campaign,utm_term,utm_content
Ad Network Click IDs (35):
| Network | Parameter(s) |
|---|---|
gclid, dclid, gclsrc, gbraid, wbraid, gacid (→ _campaign_id) |
|
fbclid, fb_ad_id, fb_adset_id, fb_campaign_id |
|
| TikTok | ttclid |
| Microsoft | msclkid |
twclid, clid_src |
|
li_fat_id |
|
epik |
|
rdt_cid |
|
| Snapchat | ScCid, sccid |
| Spotify | spclid |
| Quora | qclid |
| AppLovin | aleid |
| Basis | cntr_auctionId |
| Nextdoor | ndclid |
| StackAdapt | sapid |
| TheTradeDesk | ttdimp |
| Viant | viant_clid |
| Mailchimp | mc_cid |
igshid |
|
| Branch | _branch_match_id |
| Adjust | adj_t |
| Adobe/Kenshoo | s_kwcid |
| Impact Radius | irclickid |
| Affiliate | aff_id, affiliate_id |
Development URL Filtering:
The SDK automatically filters out development URLs to prevent false attribution:
localhost,127.0.0.1- Private IP ranges:
192.168.*.*,10.*.*.*,172.16-31.*.* - Expo development client URLs
- React Native debugger URLs
Example Deep Link Event:
{
event: 'Deep Link Opened',
properties: {
custom_props: {
url: 'myapp://product/123?utm_source=facebook&fbclid=abc123',
utm_source: 'facebook',
fbclid: 'abc123',
// All current device info is included
idfv: '...',
advertisingId: '...',
att_status: 'authorized',
app_version: '1.0.0',
user_agent: '...',
}
}
}
ATT (App Tracking Transparency)
Control and monitor iOS App Tracking Transparency permission.
Auto-Request ATT
Request ATT automatically on SDK initialization:
Freshpaint.init('YOUR_API_KEY', {
autoRequestATT: true, // Show ATT prompt before first open event
});
Flow when autoRequestATT: true:
- SDK initializes
- ATT permission is requested
- User responds (or has previously responded)
Application Installedevent fires with current ATT status
When can timestamp be captured?
The SDK can capture the timestamp of when ATT permission was granted only for new requests when autoRequestATT: true.
Cannot capture timestamp when:
- User already granted permission before SDK installation
- Host app requests ATT (when
autoRequestATT: false) - Permission was granted in a previous app version
Manual ATT Control
Request ATT permission programmatically:
// Check current status (doesn't show prompt)
const status = await Freshpaint.getTrackingAuthorizationStatus();
// Returns: 'authorized' | 'denied' | 'restricted' | 'notDetermined'
// Request permission (shows prompt if notDetermined)
const status = await Freshpaint.requestTrackingAuthorization();
// Returns same status values, safe to call multiple times
Getting Advertising Identifier
// Returns Advertising ID (IDFA on iOS, GAID on Android) if authorized/available, null otherwise
const advertisingId = await Freshpaint.getAdvertisingIdentifier();
// Get IDFV (iOS only, always available)
const idfv = await Freshpaint.getIdentifierForVendor();
SKAdNetwork
iOS 11.3+ attribution framework for privacy-preserving ad attribution.
Automatic Registration
The SDK automatically registers with SKAdNetwork on first app launch (called once during Application Installed).
Version Support:
- iOS 16.1+: Uses
updatePostbackConversionValuewith coarse conversion values - iOS 15.4-16.0: Uses
updatePostbackConversionValue(fine-grained only) - iOS 11.3-15.3: Uses legacy
registerAppForAdNetworkAttribution(deprecated)
Custom Conversion Values
Update conversion values to signal post-install events to ad networks:
// Simple update (iOS 15.4+)
await Freshpaint.updateSKANConversionValue(42);
// Full update with coarse value and lock (iOS 16.1+)
await Freshpaint.updateSKANConversionValue(
42, // value: 0-63
'high', // coarseValue: 'low' | 'medium' | 'high'
true, // lockWindow: prevent further updates
);
Parameters:
value(0-63): Fine-grained conversion valuecoarseValue: iOS 16.1+ only, ignored on older versionslockWindow: iOS 16.1+ only, ignored on older versions
Returns: true if update attempted, false if not supported
Platform-Specific Attribution
iOS Attribution Data
const data = await Freshpaint.getAttributionData();
// Returns:
{
idfv: '...', // Always available
advertisingId: '...', // Only if ATT authorized (IDFA)
att_status: 'authorized', // ATT status
version: '1.0.0',
build: '123',
user_agent: '...',
persistent_device_id: '...', // Survives uninstall (Keychain)
device_id: '...', // Freshpaint device ID
is_first_launch: false, // True only on first app launch
// Attribution params from deep link (if any)
utm_source: 'facebook',
fbclid: '...',
}
Android Attribution Data
const data = await Freshpaint.getAttributionData();
// Returns (with GAID available):
{
advertisingId: '...', // Google Advertising ID (GAID) - preferred
// android_id NOT included when GAID is available (Google policy)
limit_ad_tracking: false,
version: '1.0.0',
build: '123',
user_agent: '...',
persistent_device_id: '...', // Same as advertisingId when GAID available
device_id: '...', // Freshpaint device ID
is_first_launch: false,
// Play Install Referrer (if available)
install_referrer: 'utm_source=google&utm_medium=cpc',
referrer_click_timestamp: 1234567890,
install_begin_timestamp: 1234567891,
// Attribution params from deep link (if any)
utm_source: 'google',
gclid: '...',
}
// Returns (when GAID unavailable - fallback):
{
// advertisingId NOT included when unavailable
android_id: '...', // Android ID used as fallback
limit_ad_tracking: false,
version: '1.0.0',
build: '123',
user_agent: '...',
persistent_device_id: '...', // Same as android_id when GAID unavailable
device_id: '...', // Freshpaint device ID
is_first_launch: false,
// ... other fields
}
Play Install Referrer (Android Only)
Get Play Store install referrer data separately:
const referrer = await Freshpaint.getPlayInstallReferrer();
// Returns:
{
install_referrer: 'utm_source=google&utm_medium=cpc',
referrer_click_timestamp: 1234567890, // seconds since epoch
install_begin_timestamp: 1234567891,
}
Features:
- Cached after first fetch (fast subsequent calls)
- 5-second timeout if Play Store service doesn't respond
- Returns empty object if unavailable or on iOS
Autotracking
The SDK provides comprehensive autotracking capabilities for common UI interactions. All autocaptured events are prefixed with $ (except screen_view).
React Navigation
Automatically track screen views:
import { NavigationContainer } from '@react-navigation/native';
import Freshpaint from '@freshpaint/freshpaint-react-native';
const navigationRef = React.createRef();
<NavigationContainer
ref={navigationRef}
onReady={() => {
Freshpaint.withReactNavigationAutotrack(navigationRef);
}}
>
{/* Your navigation stack */}
</NavigationContainer>;
Fires screen_view events with screen name and route parameters.
Touchables & Pressables
Wrap components to track presses:
import { TouchableOpacity, Pressable } from 'react-native';
import Freshpaint from '@freshpaint/freshpaint-react-native';
// Higher-Order Components
const FreshpaintTouchable = Freshpaint.withFreshpaintTouchableAutocapture(TouchableOpacity);
const FreshpaintPressable = Freshpaint.withFreshpaintPressableAutocapture(Pressable);
// Usage
<FreshpaintTouchable onPress={handlePress}>
<Text>Track This Press</Text>
</FreshpaintTouchable>;
Fires $element_clicked events with component metadata.
Text Input
Track text input changes:
const FreshpaintTextInput = Freshpaint.withFreshpaintTextInputAutocapture(TextInput);
<FreshpaintTextInput placeholder="Email" onChangeText={handleChange} />;
Fires $text_input_changed events.
Switches
Track switch toggles:
<Switch
value={enabled}
onValueChange={(value) => {
Freshpaint.autotrackSwitchChange(value, { switch_id: 'notifications' });
setEnabled(value);
}}
/>
Scroll Views
Track scrolling:
<ScrollView
onScroll={(event) => {
Freshpaint.autocaptureScrollView(event.nativeEvent);
}}
scrollEventThrottle={400}
>
{/* Content */}
</ScrollView>
Ignoring Elements
Prevent specific elements from being tracked:
import { FreshpaintIgnore } from '@freshpaint/freshpaint-react-native';
<FreshpaintIgnore>
<SensitiveComponent />
</FreshpaintIgnore>;
Advanced Configuration
Initialization Options
Freshpaint.init('YOUR_API_KEY', {
autoRequestATT: true, // Request ATT on iOS (default: false)
apiEndpoint: 'custom-endpoint', // Custom API endpoint
batchEvents: true, // Batch events (default: false)
eventUploadPeriodMillis: 30000, // Upload interval (default: 30s)
// ... see full documentation for all options
});
Opt Out
Disable tracking for privacy-conscious users:
// Opt out of tracking
Freshpaint.setOptOut(true);
// Re-enable tracking
Freshpaint.setOptOut(false);
API Reference
Initialization
| Method | Parameters | Description |
|---|---|---|
init() |
apiKey: string, config?: object |
Initialize the SDK |
Event Tracking
| Method | Parameters | Description |
|---|---|---|
track() |
event: string, properties?: object, options?: object |
Track a custom event |
User Management
| Method | Parameters | Description |
|---|---|---|
identify() |
userId?: string, properties?: object, options?: object |
Identify a user |
group() |
groupId?: string, properties?: object, options?: object |
Associate with a group |
reset() |
- | Clear all user state |
Custom Properties
| Method | Parameters | Description |
|---|---|---|
addEventProperties() |
properties: object |
Add properties to all events |
addInitialEventProperties() |
properties: object |
Add properties with lower priority |
removeEventProperty() |
key: string |
Remove a custom property |
Attribution
| Method | Returns | Description |
|---|---|---|
getAttributionData() |
Promise<object> |
Get all attribution data |
getPlayInstallReferrer() |
Promise<object> |
Get Play Install Referrer (Android) |
ATT (iOS)
| Method | Returns | Description |
|---|---|---|
getTrackingAuthorizationStatus() |
Promise<string> |
Get current ATT status |
requestTrackingAuthorization() |
Promise<string> |
Request ATT permission |
getAdvertisingIdentifier() |
Promise<string | null> |
Get Advertising ID (IDFA on iOS, GAID on Android) |
getIdentifierForVendor() |
Promise<string | null> |
Get IDFV (iOS only) |
SKAdNetwork (iOS)
| Method | Parameters | Returns | Description |
|---|---|---|---|
updateSKANConversionValue() |
value: number, coarseValue?: string, lockWindow?: boolean |
Promise<boolean> |
Update conversion value |
Privacy
| Method | Parameters | Description |
|---|---|---|
setOptOut() |
enabled: boolean |
Enable/disable tracking |
Platform Support
- iOS: 13.0+
- Android: API 21+ (Android 5.0+)
- React Native: 0.70.0+
License
MIT
Support
- Documentation: https://documentation.freshpaint.io
- Issues: https://github.com/freshpaint-io/freshpaint-react-native/issues
- Email: support@freshpaint.io