insert-affiliate-react-native-sdk 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import DeepLinkIapProvider from "./DeepLinkIapProvider";
2
2
  import useDeepLinkIapProvider from "./useDeepLinkIapProvider";
3
3
  export { DeepLinkIapProvider, useDeepLinkIapProvider };
4
+ export type { InsertAffiliateIdentifierChangeCallback } from "./DeepLinkIapProvider";
@@ -6,11 +6,15 @@ declare const useDeepLinkIapProvider: () => {
6
6
  }, iapticAppId: string, iapticAppName: string, iapticPublicKey: string) => Promise<boolean>;
7
7
  storeExpectedStoreTransaction: (purchaseToken: string) => Promise<void>;
8
8
  returnUserAccountTokenAndStoreExpectedTransaction: () => Promise<string | null>;
9
- returnInsertAffiliateIdentifier: () => Promise<string | null>;
9
+ returnInsertAffiliateIdentifier: (ignoreTimeout?: boolean) => Promise<string | null>;
10
+ isAffiliateAttributionValid: () => Promise<boolean>;
11
+ getAffiliateStoredDate: () => Promise<Date | null>;
10
12
  trackEvent: (eventName: string) => Promise<void>;
11
13
  setShortCode: (shortCode: string) => Promise<void>;
12
14
  setInsertAffiliateIdentifier: (referringLink: string) => Promise<void | string>;
13
- initialize: (code: string | null, verboseLogging?: boolean) => Promise<void>;
15
+ setInsertAffiliateIdentifierChangeCallback: (callback: import("./DeepLinkIapProvider").InsertAffiliateIdentifierChangeCallback | null) => void;
16
+ handleInsertLinks: (url: string) => Promise<boolean>;
17
+ initialize: (code: string | null, verboseLogging?: boolean, insertLinksEnabled?: boolean, insertLinksClipboardEnabled?: boolean, affiliateAttributionActiveTime?: number) => Promise<void>;
14
18
  isInitialized: boolean;
15
19
  OfferCode: string | null;
16
20
  };
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const react_1 = require("react");
4
4
  const DeepLinkIapProvider_1 = require("./DeepLinkIapProvider");
5
5
  const useDeepLinkIapProvider = () => {
6
- const { referrerLink, userId, validatePurchaseWithIapticAPI, storeExpectedStoreTransaction, returnUserAccountTokenAndStoreExpectedTransaction, returnInsertAffiliateIdentifier, trackEvent, setShortCode, setInsertAffiliateIdentifier, initialize, isInitialized, OfferCode, } = (0, react_1.useContext)(DeepLinkIapProvider_1.DeepLinkIapContext);
6
+ const { referrerLink, userId, validatePurchaseWithIapticAPI, storeExpectedStoreTransaction, returnUserAccountTokenAndStoreExpectedTransaction, returnInsertAffiliateIdentifier, isAffiliateAttributionValid, getAffiliateStoredDate, trackEvent, setShortCode, setInsertAffiliateIdentifier, setInsertAffiliateIdentifierChangeCallback, handleInsertLinks, initialize, isInitialized, OfferCode, } = (0, react_1.useContext)(DeepLinkIapProvider_1.DeepLinkIapContext);
7
7
  return {
8
8
  referrerLink,
9
9
  userId,
@@ -11,9 +11,13 @@ const useDeepLinkIapProvider = () => {
11
11
  storeExpectedStoreTransaction,
12
12
  returnUserAccountTokenAndStoreExpectedTransaction,
13
13
  returnInsertAffiliateIdentifier,
14
+ isAffiliateAttributionValid,
15
+ getAffiliateStoredDate,
14
16
  trackEvent,
15
17
  setShortCode,
16
18
  setInsertAffiliateIdentifier,
19
+ setInsertAffiliateIdentifierChangeCallback,
20
+ handleInsertLinks,
17
21
  initialize,
18
22
  isInitialized,
19
23
  OfferCode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insert-affiliate-react-native-sdk",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "description": "A package for connecting with the Insert Affiliate Platform to add app based affiliate marketing.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,15 +14,31 @@
14
14
  ],
15
15
  "author": "Michael Butler",
16
16
  "license": "MIT",
17
+ "dependencies": {
18
+ "react-native-play-install-referrer": "^1.1.9"
19
+ },
20
+ "peerDependencies": {
21
+ "@react-native-async-storage/async-storage": ">=1.0.0",
22
+ "@react-native-clipboard/clipboard": ">=1.16.0",
23
+ "@react-native-community/netinfo": ">=11.4.0",
24
+ "axios": ">=1.0.0",
25
+ "react": ">=16.0.0",
26
+ "react-native": ">=0.60.0",
27
+ "react-native-device-info": ">=10.0.0"
28
+ },
17
29
  "devDependencies": {
18
30
  "@jeremybarbet/apple-api-types": "^1.4.1",
19
31
  "@react-native-async-storage/async-storage": "^2.0.0",
32
+ "@react-native-clipboard/clipboard": "^1.16.3",
33
+ "@react-native-community/netinfo": "^11.4.1",
20
34
  "@types/react": "^18.3.12",
21
35
  "@types/react-native": "^0.72.8",
22
36
  "axios": "^1.7.7",
23
37
  "react": "^18.3.1",
24
38
  "react-native": "^0.76.1",
25
39
  "react-native-branch": "^6.4.0",
40
+ "react-native-device-info": "^10.14.0",
41
+ "react-native-play-install-referrer": "^1.1.9",
26
42
  "typescript": "^5.6.3"
27
43
  }
28
44
  }
package/readme.md CHANGED
@@ -23,11 +23,30 @@ To get started with the InsertAffiliateReactNative SDK:
23
23
 
24
24
  To integrate the InsertAffiliateReactNative SDK into your app:
25
25
 
26
- 1. Install the NPM package.
26
+ 1. Install the NPM package and its required peer dependencies.
27
27
  ```bash
28
28
  npm install insert-affiliate-react-native-sdk
29
29
  ```
30
30
 
31
+ 2. Install the required peer dependencies:
32
+ ```bash
33
+ npm install @react-native-async-storage/async-storage @react-native-clipboard/clipboard @react-native-community/netinfo react-native-device-info axios
34
+ ```
35
+
36
+ ### Required Dependencies
37
+
38
+ The SDK requires the following peer dependencies to function properly:
39
+
40
+ - **`@react-native-async-storage/async-storage`** (>= 1.0.0) - For persistent storage of affiliate identifiers and user data
41
+ - **`@react-native-clipboard/clipboard`** (>= 1.16.0) - For clipboard-based affiliate link detection (Insert Links feature)
42
+ - **`@react-native-community/netinfo`** (>= 11.4.0) - For network connectivity detection and system information collection
43
+ - **`react-native-device-info`** (>= 10.0.0) - For device information and system data collection
44
+ - **`axios`** (>= 1.0.0) - For API communication with Insert Affiliate services
45
+ - **`react`** (>= 16.0.0) - React framework
46
+ - **`react-native`** (>= 0.60.0) - React Native framework
47
+
48
+ **Note**: These dependencies must be installed in your app for the SDK to work. If any are missing, you'll get runtime errors when the SDK tries to use them.
49
+
31
50
  ## Architecture Overview
32
51
 
33
52
  The SDK uses a clean, two-file architecture:
@@ -83,7 +102,9 @@ const App = () => {
83
102
 
84
103
  ### Verbose Logging (Optional)
85
104
 
86
- For debugging and troubleshooting, you can enable verbose logging to get detailed insights into the SDK's operations:
105
+ By default, the SDK operates silently to avoid interrupting the user experience. However, you can enable verbose logging to see visual confirmation when affiliate attribution is processed. This is particularly useful for debugging during development or TestFlight testing.
106
+
107
+ #### Enable Verbose Logging
87
108
 
88
109
  ```javascript
89
110
  const Child = () => {
@@ -102,7 +123,7 @@ const Child = () => {
102
123
 
103
124
  - **Initialization Process**: SDK startup, company code validation, AsyncStorage operations
104
125
  - **Data Management**: User ID generation, referrer link storage, company code state management
105
- - **Deep Link Processing**: Input validation, short code detection, API conversion process
126
+ - **Deep Link / Insert Link Processing**: Input validation, short code detection, API conversion process
106
127
  - **API Communication**: Request/response details for all server calls
107
128
  - **Event Tracking**: Event parameters, payload construction, success/failure status
108
129
  - **Purchase Operations**: Transaction storage, token validation, webhook processing
@@ -130,13 +151,50 @@ const Child = () => {
130
151
 
131
152
  ⚠️ **Important**: Disable verbose logging in production builds to avoid exposing sensitive debugging information and to optimize performance.
132
153
 
154
+ ### Insert Link and Clipboard Control (BETA)
155
+ We are currently beta testing our in-house deep linking provider, Insert Links, which generates links for use with your affiliates.
156
+
157
+ For larger projects where accuracy is critical, we recommend using established third-party deep linking platforms to generate the links you use within Insert Affiliate - such as Appsflyer or Branch.io, as described in the rest of this README.
158
+
159
+ If you encounter any issues while using Insert Links, please raise an issue on this GitHub repository or contact us directly at michael@insertaffiliate.com
160
+
161
+ #### Initialize with Insert Links
162
+
163
+ When using Insert Affiliate's built-in deep link handling (Insert Links), you can enable these features during initialization:
164
+
165
+ ```javascript
166
+ const Child = () => {
167
+ const { initialize, isInitialized } = useDeepLinkIapProvider();
168
+
169
+ useEffect(() => {
170
+ if (!isInitialized) {
171
+ initialize(
172
+ "{{ your-company-code }}",
173
+ false, // Enable for debugging
174
+ true, // Enables Insert Links
175
+ true, // Enable Insert Links Clipboard access to avoid permission prompt
176
+ 604800 // Optional: Attribution timeout in seconds (7 days)
177
+ );
178
+ }
179
+ }, [initialize, isInitialized]);
180
+ }
181
+ ```
182
+
183
+ **When to use `insertLinksEnabled`:**
184
+ - Set to `true` (default: `false`) if you are using Insert Affiliate's built-in deep link and universal link handling (Insert Links)
185
+ - Set to `false` if you are using an external provider for deep links
186
+
187
+ **When to use `insertLinksClipboardEnabled`:**
188
+ - Set to `true` (default: `false`) if you are using Insert Affiliate's built-in deep links (Insert Links) **and** would like to improve the effectiveness of our deep links through the clipboard
189
+ - **Important caveat**: This will trigger a system prompt asking the user for permission to access the clipboard when the SDK initializes
190
+
133
191
 
134
192
  ## In-App Purchase Setup [Required]
135
193
  Insert Affiliate requires a Receipt Verification platform to validate in-app purchases. You must choose **one** of our supported partners:
136
194
  - [RevenueCat](https://www.revenuecat.com/)
137
195
  - [Iaptic](https://www.iaptic.com/account)
138
- - [App Store Direct Integration](#app-store-direct-integration)
139
- - [Google Play Store Direct Integration](#google-play-store-direct-integration)
196
+ - [App Store Direct Integration](#option-3-app-store-direct-integration)
197
+ - [Google Play Store Direct Integration](#option-4-google-play-store-direct-integration)
140
198
 
141
199
  ### Option 1: RevenueCat Integration
142
200
  #### Step 1. Code Setup
@@ -145,7 +203,6 @@ First, complete the [RevenueCat SDK installation](https://www.revenuecat.com/doc
145
203
  ```javascript
146
204
  import React, {useEffect} from 'react';
147
205
  import {AppRegistry} from 'react-native';
148
- import branch from 'react-native-branch';
149
206
  import App from './App';
150
207
  import {name as appName} from './app.json';
151
208
  import {useDeepLinkIapProvider, DeepLinkIapProvider} from 'insert-affiliate-react-native-sdk';
@@ -372,7 +429,7 @@ useEffect(() => {
372
429
 
373
430
  ## Deep Link Setup [Required]
374
431
 
375
- Insert Affiliate requires a Deep Linking platform to create links for your affiliates. Our platform works with **any** deep linking provider, and you only need to follow these steps:
432
+ Insert Affiliate requires a Deep Linking platform to create links for your affiliates. Our platform works with **any** deep linking provider. Below are examples for popular providers including Branch.io and AppsFlyer:
376
433
  1. **Create a deep link** in your chosen third-party platform and pass it to our dashboard when an affiliate signs up.
377
434
  2. **Handle deep link clicks** in your app by passing the clicked link:
378
435
  ```javascript
@@ -380,6 +437,159 @@ Insert Affiliate requires a Deep Linking platform to create links for your affil
380
437
  ```
381
438
  3. **Integrate with a Receipt Verification platform** by using the result from `setInsertAffiliateIdentifier` to log in or set your application’s username. Examples below include [**Iaptic**](https://github.com/Insert-Affiliate/InsertAffiliateReactNativeSDK?tab=readme-ov-file#example-with-iaptic) and [**RevenueCat**](https://github.com/Insert-Affiliate/InsertAffiliateReactNativeSDK?tab=readme-ov-file#example-with-revenuecat)
382
439
 
440
+
441
+
442
+ ### Deep Linking with Insert Links
443
+
444
+ Insert Links by Insert Affiliate supports deferred deep linking into your app. This allows you to track affiliate attribution when end users are referred to your app by clicking on one of your affiliates Insert Links.
445
+
446
+ #### Initial Setup
447
+
448
+ 1. Before you can use Insert Links, you must complete the setup steps in [our docs](https://docs.insertaffiliate.com/insert-links)
449
+
450
+ 2. **Initialization** of the Insert Affiliate SDK with Insert Links
451
+
452
+ You must enable *insertLinksEnabled* when [initialising our SDK](https://github.com/Insert-Affiliate/InsertAffiliateReactNativeSDK?tab=readme-ov-file#initialize-with-insert-links)
453
+
454
+ **Handle Insert Links** in your React Native app
455
+
456
+ The React Native SDK handles deep links in ALL scenarios:
457
+
458
+ - **App Not Running (Cold Start)**: When user clicks a deep link and app is not running, the app launches and processes the URL
459
+ - **App Running (Warm Start)**: When user clicks a deep link while app is already running, processes the URL immediately
460
+ - **App Backgrounded**: When user clicks a deep link while app is backgrounded, brings app to foreground and processes the URL
461
+ - **Automatic Processing**: Parses Insert Link URLs and sets affiliate identifiers without additional code
462
+
463
+ 3. **Platform Specific** Setup
464
+
465
+ ##### iOS Additional Setup (required)
466
+
467
+ To enable deep linking and universal links on iOS, you need to configure your app's Info.plist and AppDelegate files.
468
+
469
+ **AppDelegate Setup**
470
+
471
+ Update your `ios/YourApp/AppDelegate.mm` (or `AppDelegate.m`) file:
472
+
473
+ ```objc
474
+ #import <React/RCTLinkingManager.h>
475
+
476
+ // Handle URL opening when app is already running (iOS 9+)
477
+ - (BOOL)application:(UIApplication *)application
478
+ openURL:(NSURL *)url
479
+ options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
480
+ {
481
+ return [RCTLinkingManager application:application openURL:url options:options];
482
+ }
483
+
484
+ // Handle URL opening (iOS 8 and below - for backward compatibility)
485
+ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
486
+ sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
487
+ {
488
+ return [RCTLinkingManager application:application openURL:url
489
+ sourceApplication:sourceApplication annotation:annotation];
490
+ }
491
+
492
+ // Handle universal links (iOS 9+)
493
+ - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
494
+ restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
495
+ {
496
+ return [RCTLinkingManager application:application
497
+ continueUserActivity:userActivity
498
+ restorationHandler:restorationHandler];
499
+ }
500
+ ```
501
+
502
+ 4. **Receipt Verification Integration Examples when Using Insert Links**
503
+
504
+ The SDK provides a callback mechanism that triggers whenever the affiliate identifier changes. This is perfect for integrating with receipt verification platforms.
505
+
506
+ ##### With RevenueCat
507
+
508
+ Set up the callback to automatically update RevenueCat when the affiliate identifier changes:
509
+
510
+ ```javascript
511
+ import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
512
+ import Purchases from 'react-native-purchases';
513
+
514
+ const App = () => {
515
+ const { setInsertAffiliateIdentifierChangeCallback } = useDeepLinkIapProvider();
516
+
517
+ useEffect(() => {
518
+ // Set up callback to handle affiliate identifier changes
519
+ setInsertAffiliateIdentifierChangeCallback(async (identifier) => {
520
+ if (identifier) {
521
+ // Update RevenueCat with the affiliate identifier
522
+ await Purchases.setAttributes({"insert_affiliate": identifier});
523
+ }
524
+ });
525
+
526
+ // Cleanup on unmount
527
+ return () => {
528
+ setInsertAffiliateIdentifierChangeCallback(null);
529
+ };
530
+ }, []);
531
+
532
+ return <YourAppContent />;
533
+ };
534
+ ```
535
+
536
+ ##### With Apphud
537
+
538
+ ```javascript
539
+ import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
540
+ import Apphud from 'react-native-apphud';
541
+
542
+ const App = () => {
543
+ const { setInsertAffiliateIdentifierChangeCallback } = useDeepLinkIapProvider();
544
+
545
+ useEffect(() => {
546
+ setInsertAffiliateIdentifierChangeCallback(async (identifier) => {
547
+ if (identifier) {
548
+ // Update Apphud with the affiliate identifier
549
+ await Apphud.setUserProperty("insert_affiliate", identifier, false);
550
+ }
551
+ });
552
+
553
+ return () => {
554
+ setInsertAffiliateIdentifierChangeCallback(null);
555
+ };
556
+ }, []);
557
+
558
+ return <YourAppContent />;
559
+ };
560
+ ```
561
+
562
+ ##### With Iaptic
563
+
564
+ ```javascript
565
+ import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
566
+ import InAppPurchase from 'react-native-iaptic';
567
+
568
+ const App = () => {
569
+ const { setInsertAffiliateIdentifierChangeCallback } = useDeepLinkIapProvider();
570
+
571
+ useEffect(() => {
572
+ setInsertAffiliateIdentifierChangeCallback(async (identifier) => {
573
+ if (identifier) {
574
+ // Initialize Iaptic with the affiliate identifier
575
+ await InAppPurchase.initialize({
576
+ iapProducts: iapProductsArray,
577
+ validatorUrlString: "https://validator.iaptic.com/v3/validate?appName={{ your_iaptic_app_name }}&apiKey={{ your_iaptic_app_key_goes_here }}",
578
+ applicationUsername: identifier
579
+ });
580
+ }
581
+ });
582
+
583
+ return () => {
584
+ setInsertAffiliateIdentifierChangeCallback(null);
585
+ };
586
+ }, []);
587
+
588
+ return <YourAppContent />;
589
+ };
590
+ ```
591
+
592
+
383
593
  ### Deep Linking with Branch.io
384
594
  To set up deep linking with Branch.io, follow these steps:
385
595
 
@@ -485,6 +695,155 @@ const RootComponent = () => {
485
695
  };
486
696
  ```
487
697
 
698
+ ### Deep Linking with AppsFlyer
699
+ To set up deep linking with AppsFlyer, follow these steps:
700
+
701
+ 1. Create a [OneLink](https://support.appsflyer.com/hc/en-us/articles/208874366-Create-a-OneLink-link-for-your-campaigns) in AppsFlyer and pass it to our dashboard when an affiliate signs up.
702
+ - Example: [Create Affiliate](https://docs.insertaffiliate.com/create-affiliate).
703
+ 2. Initialize AppsFlyer SDK and set up deep link handling in your app.
704
+
705
+ #### Platform Setup
706
+ Complete the deep linking setup for AppsFlyer by following their official documentation:
707
+ - [AppsFlyer Deferred Deep Link Integration Guide](https://dev.appsflyer.com/hc/docs/deeplinkintegrate)
708
+
709
+ This covers all platform-specific configurations including:
710
+ - iOS: Info.plist configuration, AppDelegate setup, and universal links
711
+ - Android: AndroidManifest.xml intent filters, MainActivity setup, and App Links
712
+ - Testing and troubleshooting for both platforms
713
+
714
+ #### Example with RevenueCat
715
+
716
+ ```javascript
717
+ import React, { useEffect } from 'react';
718
+ import { Platform } from 'react-native';
719
+ import appsFlyer from 'react-native-appsflyer';
720
+ import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
721
+ import Purchases from 'react-native-purchases';
722
+
723
+ const DeepLinkHandler = () => {
724
+ const { setInsertAffiliateIdentifier, isInitialized } = useDeepLinkIapProvider();
725
+
726
+ useEffect(() => {
727
+ if (!isInitialized) return;
728
+
729
+ // Initialize AppsFlyer
730
+ const initAppsFlyer = async () => {
731
+ try {
732
+ const initOptions = {
733
+ devKey: 'your-appsflyer-dev-key',
734
+ isDebug: true,
735
+ appId: Platform.OS === 'ios' ? 'your-ios-app-id' : 'your-android-package-name',
736
+ };
737
+
738
+ await appsFlyer.initSdk(initOptions);
739
+ } catch (error) {
740
+ console.error('AppsFlyer initialization error:', error);
741
+ }
742
+ };
743
+
744
+ // Handle deep link data
745
+ const handleDeepLink = async (deepLinkData) => {
746
+ if (deepLinkData && deepLinkData.data) {
747
+ let referringLink = deepLinkData.data.link || deepLinkData.data.deep_link_value;
748
+
749
+ if (referringLink) {
750
+ try {
751
+ let insertAffiliateIdentifier = await setInsertAffiliateIdentifier(referringLink);
752
+
753
+ if (insertAffiliateIdentifier) {
754
+ await Purchases.setAttributes({"insert_affiliate": insertAffiliateIdentifier});
755
+ }
756
+ } catch (err) {
757
+ console.error('Error setting affiliate identifier:', err);
758
+ }
759
+ }
760
+ }
761
+ };
762
+
763
+ // Listen for both deep link types
764
+ appsFlyer.onDeepLink(handleDeepLink);
765
+ appsFlyer.onAppOpenAttribution(handleDeepLink);
766
+
767
+ initAppsFlyer();
768
+ }, [setInsertAffiliateIdentifier, isInitialized]);
769
+
770
+ return <App />;
771
+ };
772
+
773
+ const RootComponent = () => {
774
+ return (
775
+ <DeepLinkIapProvider>
776
+ <DeepLinkHandler />
777
+ </DeepLinkIapProvider>
778
+ );
779
+ };
780
+
781
+ AppRegistry.registerComponent(appName, () => RootComponent);
782
+ ```
783
+
784
+ #### Example with Iaptic / App Store Direct Integration / Google Play Direct Integration
785
+
786
+ ```javascript
787
+ import React, { useEffect } from 'react';
788
+ import { Platform } from 'react-native';
789
+ import appsFlyer from 'react-native-appsflyer';
790
+ import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
791
+
792
+ const DeepLinkHandler = () => {
793
+ const { setInsertAffiliateIdentifier, isInitialized } = useDeepLinkIapProvider();
794
+
795
+ useEffect(() => {
796
+ if (!isInitialized) return;
797
+
798
+ // Initialize AppsFlyer
799
+ const initAppsFlyer = async () => {
800
+ try {
801
+ const initOptions = {
802
+ devKey: 'your-appsflyer-dev-key',
803
+ isDebug: true,
804
+ appId: Platform.OS === 'ios' ? 'your-ios-app-id' : 'your-android-package-name',
805
+ };
806
+
807
+ await appsFlyer.initSdk(initOptions);
808
+ } catch (error) {
809
+ console.error('AppsFlyer initialization error:', error);
810
+ }
811
+ };
812
+
813
+ // Handle deep link data
814
+ const handleDeepLink = async (deepLinkData) => {
815
+ if (deepLinkData && deepLinkData.data) {
816
+ let referringLink = deepLinkData.data.link || deepLinkData.data.deep_link_value;
817
+
818
+ if (referringLink) {
819
+ try {
820
+ await setInsertAffiliateIdentifier(referringLink);
821
+ } catch (err) {
822
+ console.error('Error setting affiliate identifier:', err);
823
+ }
824
+ }
825
+ }
826
+ };
827
+
828
+ // Listen for both deep link types
829
+ appsFlyer.onDeepLink(handleDeepLink);
830
+ appsFlyer.onAppOpenAttribution(handleDeepLink);
831
+
832
+ initAppsFlyer();
833
+ }, [setInsertAffiliateIdentifier, isInitialized]);
834
+
835
+ return <App />;
836
+ };
837
+
838
+ const RootComponent = () => {
839
+ return (
840
+ <DeepLinkIapProvider>
841
+ <DeepLinkHandler />
842
+ </DeepLinkIapProvider>
843
+ );
844
+ };
845
+ ```
846
+
488
847
  ## Additional Features
489
848
 
490
849
  ### 1. Event Tracking (Beta)
@@ -869,3 +1228,84 @@ Short codes must meet the following criteria:
869
1228
  onPress={() => setShortCode('JOIN_123')}
870
1229
  />
871
1230
  ```
1231
+
1232
+ ### Attribution Timeout
1233
+
1234
+ You can configure how long an affiliate link attribution remains active after being clicked. This allows you to control the attribution window for commissions.
1235
+
1236
+ #### Basic Usage
1237
+
1238
+ When initializing the SDK, you can specify the attribution timeout in seconds:
1239
+
1240
+ ```javascript
1241
+ const Child = () => {
1242
+ const { initialize, isInitialized } = useDeepLinkIapProvider();
1243
+
1244
+ useEffect(() => {
1245
+ if (!isInitialized) {
1246
+ // Set attribution timeout to 7 days (7 * 24 * 60 * 60 = 604800 seconds)
1247
+ initialize(
1248
+ "{{ your-company-code }}",
1249
+ false, // verbose logging
1250
+ false, // insert links enabled
1251
+ false, // insert links clipboard enabled
1252
+ 604800 // attribution timeout in seconds
1253
+ );
1254
+ }
1255
+ }, [initialize, isInitialized]);
1256
+ }
1257
+ ```
1258
+
1259
+ **When to use `affiliateAttributionActiveTime`:**
1260
+ - Set to a number in seconds to define how long affiliate attributions remain active
1261
+ - Set to `null` or omit to disable attribution timeout (attribution never expires)
1262
+ - Common values: 86400 (1 day), 604800 (7 days), 2592000 (30 days)
1263
+
1264
+ #### Common Timeout Values
1265
+
1266
+ ```javascript
1267
+ // 1 day
1268
+ initialize("your-company-code", false, false, false, 86400);
1269
+
1270
+ // 7 days (default for many platforms)
1271
+ initialize("your-company-code", false, false, false, 604800);
1272
+
1273
+ // 30 days
1274
+ initialize("your-company-code", false, false, false, 2592000);
1275
+
1276
+ // No timeout (attribution never expires)
1277
+ initialize("your-company-code", false, false, false); // or pass null/undefined
1278
+ ```
1279
+
1280
+ #### Advanced Usage
1281
+
1282
+ The SDK provides methods to work with attribution timeouts:
1283
+
1284
+ ```javascript
1285
+ const {
1286
+ returnInsertAffiliateIdentifier,
1287
+ isAffiliateAttributionValid,
1288
+ getAffiliateStoredDate
1289
+ } = useDeepLinkIapProvider();
1290
+
1291
+ // Get affiliate identifier (respects timeout)
1292
+ const identifier = await returnInsertAffiliateIdentifier();
1293
+
1294
+ // Get affiliate identifier ignoring timeout
1295
+ const rawIdentifier = await returnInsertAffiliateIdentifier(true);
1296
+
1297
+ // Check if attribution is still valid
1298
+ const isValid = await isAffiliateAttributionValid();
1299
+
1300
+ // Get the date when affiliate was first stored
1301
+ const storedDate = await getAffiliateStoredDate();
1302
+ ```
1303
+
1304
+ #### How It Works
1305
+
1306
+ 1. **Attribution Storage**: When an affiliate link is clicked and processed, the SDK stores both the affiliate identifier and the current timestamp
1307
+ 2. **Timeout Check**: When `returnInsertAffiliateIdentifier()` is called, the SDK checks if the stored attribution is still within the timeout window
1308
+ 3. **Expired Attribution**: If the attribution has expired, the method returns `null` instead of the affiliate identifier
1309
+ 4. **Bypass Option**: You can bypass the timeout check by passing `true` to `returnInsertAffiliateIdentifier(true)`
1310
+
1311
+ This ensures that affiliates are only credited for purchases made within the specified attribution window, providing fair and accurate commission tracking.