insert-affiliate-react-native-sdk 1.9.0 → 1.11.1
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/.claude/settings.local.json +8 -2
- package/dist/DeepLinkIapProvider.js +362 -158
- package/docs/deep-linking-appsflyer.md +385 -0
- package/docs/deep-linking-branch.md +351 -0
- package/docs/dynamic-offer-codes.md +369 -0
- package/package.json +1 -1
- package/readme.md +638 -1071
- package/src/DeepLinkIapProvider.tsx +369 -113
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Branch.io Deep Linking Integration
|
|
2
|
+
|
|
3
|
+
This guide shows how to integrate InsertAffiliateReactNative SDK with Branch.io for deep linking attribution.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- [Branch SDK for React Native](https://help.branch.io/developers-hub/docs/react-native) installed and configured
|
|
8
|
+
- Create a Branch deep link and provide it to affiliates via the [Insert Affiliate dashboard](https://app.insertaffiliate.com/affiliates)
|
|
9
|
+
|
|
10
|
+
## Platform Setup
|
|
11
|
+
|
|
12
|
+
Complete the deep linking setup for Branch by following their official documentation:
|
|
13
|
+
- [Branch React Native SDK Integration Guide](https://help.branch.io/developers-hub/docs/react-native)
|
|
14
|
+
|
|
15
|
+
This covers:
|
|
16
|
+
- iOS: Info.plist configuration, AppDelegate setup, and universal links
|
|
17
|
+
- Android: AndroidManifest.xml intent filters and App Links
|
|
18
|
+
- Testing and troubleshooting
|
|
19
|
+
|
|
20
|
+
## Integration Examples
|
|
21
|
+
|
|
22
|
+
Choose the example that matches your IAP verification platform:
|
|
23
|
+
|
|
24
|
+
### Example with RevenueCat
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import React, { useEffect } from 'react';
|
|
28
|
+
import { AppRegistry } from 'react-native';
|
|
29
|
+
import branch from 'react-native-branch';
|
|
30
|
+
import Purchases from 'react-native-purchases';
|
|
31
|
+
import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
32
|
+
import App from './App';
|
|
33
|
+
import { name as appName } from './app.json';
|
|
34
|
+
|
|
35
|
+
const DeepLinkHandler = () => {
|
|
36
|
+
const { setInsertAffiliateIdentifier } = useDeepLinkIapProvider();
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
40
|
+
if (error) {
|
|
41
|
+
console.error('Error from Branch:', error);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (params['+clicked_branch_link']) {
|
|
46
|
+
const referringLink = params['~referring_link'];
|
|
47
|
+
if (referringLink) {
|
|
48
|
+
try {
|
|
49
|
+
const insertAffiliateIdentifier = await setInsertAffiliateIdentifier(referringLink);
|
|
50
|
+
|
|
51
|
+
if (insertAffiliateIdentifier) {
|
|
52
|
+
await Purchases.setAttributes({ "insert_affiliate": insertAffiliateIdentifier });
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.error('Error setting affiliate identifier:', err);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
branchSubscription();
|
|
63
|
+
};
|
|
64
|
+
}, [setInsertAffiliateIdentifier]);
|
|
65
|
+
|
|
66
|
+
return <App />;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const RootComponent = () => {
|
|
70
|
+
return (
|
|
71
|
+
<DeepLinkIapProvider>
|
|
72
|
+
<DeepLinkHandler />
|
|
73
|
+
</DeepLinkIapProvider>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
AppRegistry.registerComponent(appName, () => RootComponent);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Example with Adapty
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
import React, { useEffect, useRef } from 'react';
|
|
84
|
+
import { AppRegistry } from 'react-native';
|
|
85
|
+
import branch from 'react-native-branch';
|
|
86
|
+
import { adapty } from 'react-native-adapty';
|
|
87
|
+
import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
88
|
+
import App from './App';
|
|
89
|
+
import { name as appName } from './app.json';
|
|
90
|
+
|
|
91
|
+
const DeepLinkHandler = () => {
|
|
92
|
+
const { setInsertAffiliateIdentifier } = useDeepLinkIapProvider();
|
|
93
|
+
const adaptyActivationPromiseRef = useRef(null);
|
|
94
|
+
|
|
95
|
+
// Initialize Adapty SDK
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const initAdapty = async () => {
|
|
98
|
+
try {
|
|
99
|
+
adaptyActivationPromiseRef.current = adapty.activate('YOUR_ADAPTY_PUBLIC_SDK_KEY', {
|
|
100
|
+
__ignoreActivationOnFastRefresh: __DEV__,
|
|
101
|
+
});
|
|
102
|
+
await adaptyActivationPromiseRef.current;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Failed to activate Adapty SDK:', error);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (!adaptyActivationPromiseRef.current) {
|
|
109
|
+
initAdapty();
|
|
110
|
+
}
|
|
111
|
+
}, []);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
115
|
+
if (error) {
|
|
116
|
+
console.error('Error from Branch:', error);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (params['+clicked_branch_link']) {
|
|
121
|
+
const referringLink = params['~referring_link'];
|
|
122
|
+
if (referringLink) {
|
|
123
|
+
try {
|
|
124
|
+
const insertAffiliateIdentifier = await setInsertAffiliateIdentifier(referringLink);
|
|
125
|
+
|
|
126
|
+
if (insertAffiliateIdentifier && adaptyActivationPromiseRef.current) {
|
|
127
|
+
// Wait for Adapty activation before updating profile
|
|
128
|
+
await adaptyActivationPromiseRef.current;
|
|
129
|
+
await adapty.updateProfile({
|
|
130
|
+
codableCustomAttributes: {
|
|
131
|
+
insert_affiliate: insertAffiliateIdentifier,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error('Error setting affiliate identifier:', err);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return () => {
|
|
143
|
+
branchSubscription();
|
|
144
|
+
};
|
|
145
|
+
}, [setInsertAffiliateIdentifier]);
|
|
146
|
+
|
|
147
|
+
return <App />;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const RootComponent = () => {
|
|
151
|
+
return (
|
|
152
|
+
<DeepLinkIapProvider>
|
|
153
|
+
<DeepLinkHandler />
|
|
154
|
+
</DeepLinkIapProvider>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
AppRegistry.registerComponent(appName, () => RootComponent);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Example with Apphud
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
import React, { useEffect } from 'react';
|
|
165
|
+
import { AppRegistry } from 'react-native';
|
|
166
|
+
import branch from 'react-native-branch';
|
|
167
|
+
import Apphud from 'react-native-apphud';
|
|
168
|
+
import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
169
|
+
import App from './App';
|
|
170
|
+
import { name as appName } from './app.json';
|
|
171
|
+
|
|
172
|
+
const DeepLinkHandler = () => {
|
|
173
|
+
const { setInsertAffiliateIdentifier } = useDeepLinkIapProvider();
|
|
174
|
+
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
177
|
+
if (error) {
|
|
178
|
+
console.error('Error from Branch:', error);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (params['+clicked_branch_link']) {
|
|
183
|
+
const referringLink = params['~referring_link'];
|
|
184
|
+
if (referringLink) {
|
|
185
|
+
try {
|
|
186
|
+
const insertAffiliateIdentifier = await setInsertAffiliateIdentifier(referringLink);
|
|
187
|
+
|
|
188
|
+
if (insertAffiliateIdentifier) {
|
|
189
|
+
await Apphud.setUserProperty("insert_affiliate", insertAffiliateIdentifier, false);
|
|
190
|
+
}
|
|
191
|
+
} catch (err) {
|
|
192
|
+
console.error('Error setting affiliate identifier:', err);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return () => {
|
|
199
|
+
branchSubscription();
|
|
200
|
+
};
|
|
201
|
+
}, [setInsertAffiliateIdentifier]);
|
|
202
|
+
|
|
203
|
+
return <App />;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const RootComponent = () => {
|
|
207
|
+
return (
|
|
208
|
+
<DeepLinkIapProvider>
|
|
209
|
+
<DeepLinkHandler />
|
|
210
|
+
</DeepLinkIapProvider>
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
AppRegistry.registerComponent(appName, () => RootComponent);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Example with Iaptic
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
import React, { useEffect } from 'react';
|
|
221
|
+
import { AppRegistry } from 'react-native';
|
|
222
|
+
import branch from 'react-native-branch';
|
|
223
|
+
import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
224
|
+
import App from './App';
|
|
225
|
+
import { name as appName } from './app.json';
|
|
226
|
+
|
|
227
|
+
const DeepLinkHandler = () => {
|
|
228
|
+
const { setInsertAffiliateIdentifier } = useDeepLinkIapProvider();
|
|
229
|
+
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
232
|
+
if (error) {
|
|
233
|
+
console.error('Error from Branch:', error);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (params['+clicked_branch_link']) {
|
|
238
|
+
const referringLink = params['~referring_link'];
|
|
239
|
+
if (referringLink) {
|
|
240
|
+
try {
|
|
241
|
+
await setInsertAffiliateIdentifier(referringLink);
|
|
242
|
+
console.log('Affiliate identifier set successfully.');
|
|
243
|
+
} catch (err) {
|
|
244
|
+
console.error('Error setting affiliate identifier:', err);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return () => branchSubscription();
|
|
251
|
+
}, [setInsertAffiliateIdentifier]);
|
|
252
|
+
|
|
253
|
+
return <App />;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const RootComponent = () => {
|
|
257
|
+
return (
|
|
258
|
+
<DeepLinkIapProvider>
|
|
259
|
+
<DeepLinkHandler />
|
|
260
|
+
</DeepLinkIapProvider>
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
AppRegistry.registerComponent(appName, () => RootComponent);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Example with App Store / Google Play Direct Integration
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
import React, { useEffect } from 'react';
|
|
271
|
+
import { AppRegistry } from 'react-native';
|
|
272
|
+
import branch from 'react-native-branch';
|
|
273
|
+
import { useDeepLinkIapProvider, DeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
274
|
+
import App from './App';
|
|
275
|
+
import { name as appName } from './app.json';
|
|
276
|
+
|
|
277
|
+
const DeepLinkHandler = () => {
|
|
278
|
+
const { setInsertAffiliateIdentifier } = useDeepLinkIapProvider();
|
|
279
|
+
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
282
|
+
if (error) {
|
|
283
|
+
console.error('Error from Branch:', error);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (params['+clicked_branch_link']) {
|
|
288
|
+
const referringLink = params['~referring_link'];
|
|
289
|
+
if (referringLink) {
|
|
290
|
+
try {
|
|
291
|
+
await setInsertAffiliateIdentifier(referringLink);
|
|
292
|
+
// Affiliate identifier is stored automatically for direct store integration
|
|
293
|
+
} catch (err) {
|
|
294
|
+
console.error('Error setting affiliate identifier:', err);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return () => branchSubscription();
|
|
301
|
+
}, [setInsertAffiliateIdentifier]);
|
|
302
|
+
|
|
303
|
+
return <App />;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const RootComponent = () => {
|
|
307
|
+
return (
|
|
308
|
+
<DeepLinkIapProvider>
|
|
309
|
+
<DeepLinkHandler />
|
|
310
|
+
</DeepLinkIapProvider>
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
AppRegistry.registerComponent(appName, () => RootComponent);
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Testing
|
|
318
|
+
|
|
319
|
+
Test your Branch deep link integration:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
# Test with your Branch link (iOS Simulator)
|
|
323
|
+
xcrun simctl openurl booted "https://your-app.app.link/abc123"
|
|
324
|
+
|
|
325
|
+
# Test with your Branch link (Android Emulator)
|
|
326
|
+
adb shell am start -W -a android.intent.action.VIEW -d "https://your-app.app.link/abc123"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Troubleshooting
|
|
330
|
+
|
|
331
|
+
**Problem:** `~referring_link` is null
|
|
332
|
+
- **Solution:** Ensure Branch SDK is properly initialized before Insert Affiliate SDK
|
|
333
|
+
- Verify Branch link is properly configured with your app's URI scheme
|
|
334
|
+
|
|
335
|
+
**Problem:** Deep link opens browser instead of app
|
|
336
|
+
- **Solution:** Check Branch dashboard for associated domains configuration
|
|
337
|
+
- Verify your app's entitlements include the Branch link domain (iOS)
|
|
338
|
+
- Verify AndroidManifest.xml has correct intent filters (Android)
|
|
339
|
+
|
|
340
|
+
**Problem:** Deferred deep linking not working
|
|
341
|
+
- **Solution:** Make sure you're using `branch.subscribe()` correctly
|
|
342
|
+
- Test with a fresh app install (uninstall/reinstall)
|
|
343
|
+
|
|
344
|
+
## Next Steps
|
|
345
|
+
|
|
346
|
+
After completing Branch integration:
|
|
347
|
+
1. Test deep link attribution with a test affiliate link
|
|
348
|
+
2. Verify affiliate identifier is stored correctly
|
|
349
|
+
3. Make a test purchase to confirm tracking works end-to-end
|
|
350
|
+
|
|
351
|
+
[Back to Main README](../readme.md)
|