insert-affiliate-react-native-sdk 1.12.0 → 1.14.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/DeepLinkIapProvider.js +22 -16
- package/package.json +1 -1
- package/readme.md +23 -0
- package/src/DeepLinkIapProvider.tsx +23 -15
|
@@ -56,6 +56,7 @@ const ASYNC_KEYS = {
|
|
|
56
56
|
AFFILIATE_STORED_DATE: '@app_affiliate_stored_date',
|
|
57
57
|
SDK_INIT_REPORTED: '@app_sdk_init_reported',
|
|
58
58
|
REPORTED_AFFILIATE_ASSOCIATIONS: '@app_reported_affiliate_associations',
|
|
59
|
+
SYSTEM_INFO_SENT: '@app_system_info_sent',
|
|
59
60
|
};
|
|
60
61
|
// STARTING CONTEXT IMPLEMENTATION
|
|
61
62
|
exports.DeepLinkIapContext = (0, react_1.createContext)({
|
|
@@ -151,12 +152,20 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
if (insertLinksEnabledParam && react_native_1.Platform.OS === 'ios') {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
const systemInfoSent = yield getValueFromAsync(ASYNC_KEYS.SYSTEM_INFO_SENT);
|
|
156
|
+
verboseLog(`System info sent flag: ${systemInfoSent ? 'true (skipping)' : 'false (will send)'}`);
|
|
157
|
+
if (!systemInfoSent) {
|
|
158
|
+
// Set flag immediately to prevent concurrent init calls from sending twice
|
|
159
|
+
yield saveValueInAsync(ASYNC_KEYS.SYSTEM_INFO_SENT, 'pending');
|
|
160
|
+
try {
|
|
161
|
+
const enhancedSystemInfo = yield getEnhancedSystemInfo();
|
|
162
|
+
yield sendSystemInfoToBackend(enhancedSystemInfo);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
// Remove flag on failure so it retries next launch
|
|
166
|
+
yield async_storage_1.default.removeItem(ASYNC_KEYS.SYSTEM_INFO_SENT);
|
|
167
|
+
verboseLog(`Error sending system info for clipboard check: ${error}`);
|
|
168
|
+
}
|
|
160
169
|
}
|
|
161
170
|
}
|
|
162
171
|
});
|
|
@@ -561,14 +570,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
561
570
|
}
|
|
562
571
|
// If URL scheme is used, we can straight away store the short code as the referring link
|
|
563
572
|
yield storeInsertAffiliateIdentifier({ link: shortCode, source: 'deep_link_ios' });
|
|
564
|
-
//
|
|
565
|
-
try {
|
|
566
|
-
const enhancedSystemInfo = yield getEnhancedSystemInfo();
|
|
567
|
-
yield sendSystemInfoToBackend(enhancedSystemInfo);
|
|
568
|
-
}
|
|
569
|
-
catch (error) {
|
|
570
|
-
verboseLog(`Error sending system info for deep link: ${error}`);
|
|
571
|
-
}
|
|
573
|
+
// System info not needed here - affiliate code already received via URL scheme
|
|
572
574
|
return true;
|
|
573
575
|
}
|
|
574
576
|
catch (error) {
|
|
@@ -1162,6 +1164,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1162
1164
|
}
|
|
1163
1165
|
// Check for a successful response
|
|
1164
1166
|
if (response.status >= 200 && response.status <= 299) {
|
|
1167
|
+
yield saveValueInAsync(ASYNC_KEYS.SYSTEM_INFO_SENT, 'true');
|
|
1165
1168
|
verboseLog('System info sent successfully');
|
|
1166
1169
|
}
|
|
1167
1170
|
else {
|
|
@@ -1182,7 +1185,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1182
1185
|
const isValidCharacters = /^[a-zA-Z0-9_]+$/.test(referringLink);
|
|
1183
1186
|
return isValidCharacters && referringLink.length >= 3 && referringLink.length <= 25;
|
|
1184
1187
|
};
|
|
1185
|
-
const checkAffiliateExists = (
|
|
1188
|
+
const checkAffiliateExists = (affiliateCode_1, ...args_1) => __awaiter(void 0, [affiliateCode_1, ...args_1], void 0, function* (affiliateCode, trackUsage = false) {
|
|
1186
1189
|
try {
|
|
1187
1190
|
const activeCompanyCode = yield getActiveCompanyCode();
|
|
1188
1191
|
if (!activeCompanyCode) {
|
|
@@ -1194,6 +1197,9 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1194
1197
|
companyId: activeCompanyCode,
|
|
1195
1198
|
affiliateCode: affiliateCode
|
|
1196
1199
|
};
|
|
1200
|
+
if (trackUsage) {
|
|
1201
|
+
payload.trackUsage = true;
|
|
1202
|
+
}
|
|
1197
1203
|
verboseLog(`Checking if affiliate exists: ${affiliateCode}`);
|
|
1198
1204
|
const response = yield axios_1.default.post(url, payload, {
|
|
1199
1205
|
headers: {
|
|
@@ -1267,7 +1273,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1267
1273
|
const capitalisedShortCode = shortCode.toUpperCase();
|
|
1268
1274
|
isShortCode(capitalisedShortCode);
|
|
1269
1275
|
// Check if the affiliate exists before storing
|
|
1270
|
-
const exists = yield checkAffiliateExists(capitalisedShortCode);
|
|
1276
|
+
const exists = yield checkAffiliateExists(capitalisedShortCode, true);
|
|
1271
1277
|
if (exists) {
|
|
1272
1278
|
// If affiliate exists, set the Insert Affiliate Identifier
|
|
1273
1279
|
yield storeInsertAffiliateIdentifier({ link: capitalisedShortCode, source: 'short_code_manual' });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "insert-affiliate-react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.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",
|
package/readme.md
CHANGED
|
@@ -1011,6 +1011,29 @@ const rawIdentifier = await returnInsertAffiliateIdentifier(true);
|
|
|
1011
1011
|
|
|
1012
1012
|
</details>
|
|
1013
1013
|
|
|
1014
|
+
### Prevent Affiliate Transfer
|
|
1015
|
+
|
|
1016
|
+
By default, clicking a new affiliate link will overwrite any existing attribution. Enable `preventAffiliateTransfer` to lock the first affiliate:
|
|
1017
|
+
|
|
1018
|
+
```javascript
|
|
1019
|
+
initialize(
|
|
1020
|
+
"YOUR_COMPANY_CODE",
|
|
1021
|
+
false, // verboseLogging
|
|
1022
|
+
false, // insertLinksEnabled
|
|
1023
|
+
false, // insertLinksClipboardEnabled
|
|
1024
|
+
604800, // affiliateAttributionActiveTime (7 days)
|
|
1025
|
+
true // preventAffiliateTransfer - locks first affiliate
|
|
1026
|
+
);
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
**How it works:**
|
|
1030
|
+
- When enabled, once a user is attributed to an affiliate, that attribution is locked
|
|
1031
|
+
- New affiliate links will not overwrite the existing attribution
|
|
1032
|
+
- The callback still fires with the existing affiliate data (not the new one)
|
|
1033
|
+
- Useful for preventing "affiliate stealing" where users click competitor links
|
|
1034
|
+
|
|
1035
|
+
Learn more: [Prevent Affiliate Transfer Documentation](https://docs.insertaffiliate.com/prevent-affiliate-transfer)
|
|
1036
|
+
|
|
1014
1037
|
---
|
|
1015
1038
|
|
|
1016
1039
|
## 🔍 Troubleshooting
|
|
@@ -83,6 +83,7 @@ const ASYNC_KEYS = {
|
|
|
83
83
|
AFFILIATE_STORED_DATE: '@app_affiliate_stored_date',
|
|
84
84
|
SDK_INIT_REPORTED: '@app_sdk_init_reported',
|
|
85
85
|
REPORTED_AFFILIATE_ASSOCIATIONS: '@app_reported_affiliate_associations',
|
|
86
|
+
SYSTEM_INFO_SENT: '@app_system_info_sent',
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
// Source types for affiliate association tracking
|
|
@@ -207,11 +208,19 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
if (insertLinksEnabledParam && Platform.OS === 'ios') {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
const systemInfoSent = await getValueFromAsync(ASYNC_KEYS.SYSTEM_INFO_SENT);
|
|
212
|
+
verboseLog(`System info sent flag: ${systemInfoSent ? 'true (skipping)' : 'false (will send)'}`);
|
|
213
|
+
if (!systemInfoSent) {
|
|
214
|
+
// Set flag immediately to prevent concurrent init calls from sending twice
|
|
215
|
+
await saveValueInAsync(ASYNC_KEYS.SYSTEM_INFO_SENT, 'pending');
|
|
216
|
+
try {
|
|
217
|
+
const enhancedSystemInfo = await getEnhancedSystemInfo();
|
|
218
|
+
await sendSystemInfoToBackend(enhancedSystemInfo);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
// Remove flag on failure so it retries next launch
|
|
221
|
+
await AsyncStorage.removeItem(ASYNC_KEYS.SYSTEM_INFO_SENT);
|
|
222
|
+
verboseLog(`Error sending system info for clipboard check: ${error}`);
|
|
223
|
+
}
|
|
215
224
|
}
|
|
216
225
|
}
|
|
217
226
|
};
|
|
@@ -664,13 +673,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
664
673
|
// If URL scheme is used, we can straight away store the short code as the referring link
|
|
665
674
|
await storeInsertAffiliateIdentifier({ link: shortCode, source: 'deep_link_ios' });
|
|
666
675
|
|
|
667
|
-
//
|
|
668
|
-
try {
|
|
669
|
-
const enhancedSystemInfo = await getEnhancedSystemInfo();
|
|
670
|
-
await sendSystemInfoToBackend(enhancedSystemInfo);
|
|
671
|
-
} catch (error) {
|
|
672
|
-
verboseLog(`Error sending system info for deep link: ${error}`);
|
|
673
|
-
}
|
|
676
|
+
// System info not needed here - affiliate code already received via URL scheme
|
|
674
677
|
|
|
675
678
|
return true;
|
|
676
679
|
} catch (error) {
|
|
@@ -1347,6 +1350,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
1347
1350
|
|
|
1348
1351
|
// Check for a successful response
|
|
1349
1352
|
if (response.status >= 200 && response.status <= 299) {
|
|
1353
|
+
await saveValueInAsync(ASYNC_KEYS.SYSTEM_INFO_SENT, 'true');
|
|
1350
1354
|
verboseLog('System info sent successfully');
|
|
1351
1355
|
} else {
|
|
1352
1356
|
verboseLog(`Failed to send system info with status code: ${response.status}`);
|
|
@@ -1367,7 +1371,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
1367
1371
|
return isValidCharacters && referringLink.length >= 3 && referringLink.length <= 25;
|
|
1368
1372
|
};
|
|
1369
1373
|
|
|
1370
|
-
const checkAffiliateExists = async (affiliateCode: string): Promise<boolean> => {
|
|
1374
|
+
const checkAffiliateExists = async (affiliateCode: string, trackUsage: boolean = false): Promise<boolean> => {
|
|
1371
1375
|
try {
|
|
1372
1376
|
const activeCompanyCode = await getActiveCompanyCode();
|
|
1373
1377
|
if (!activeCompanyCode) {
|
|
@@ -1376,11 +1380,15 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
1376
1380
|
}
|
|
1377
1381
|
|
|
1378
1382
|
const url = 'https://api.insertaffiliate.com/V1/checkAffiliateExists';
|
|
1379
|
-
const payload = {
|
|
1383
|
+
const payload: Record<string, any> = {
|
|
1380
1384
|
companyId: activeCompanyCode,
|
|
1381
1385
|
affiliateCode: affiliateCode
|
|
1382
1386
|
};
|
|
1383
1387
|
|
|
1388
|
+
if (trackUsage) {
|
|
1389
|
+
payload.trackUsage = true;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1384
1392
|
verboseLog(`Checking if affiliate exists: ${affiliateCode}`);
|
|
1385
1393
|
|
|
1386
1394
|
const response = await axios.post(url, payload, {
|
|
@@ -1463,7 +1471,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
1463
1471
|
isShortCode(capitalisedShortCode);
|
|
1464
1472
|
|
|
1465
1473
|
// Check if the affiliate exists before storing
|
|
1466
|
-
const exists = await checkAffiliateExists(capitalisedShortCode);
|
|
1474
|
+
const exists = await checkAffiliateExists(capitalisedShortCode, true);
|
|
1467
1475
|
|
|
1468
1476
|
if (exists) {
|
|
1469
1477
|
// If affiliate exists, set the Insert Affiliate Identifier
|