insert-affiliate-react-native-sdk 1.5.1 → 1.6.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 -0
- package/dist/DeepLinkIapProvider.d.ts +1 -0
- package/dist/DeepLinkIapProvider.js +83 -0
- package/dist/useDeepLinkIapProvider.d.ts +1 -0
- package/dist/useDeepLinkIapProvider.js +3 -2
- package/package.json +1 -1
- package/readme.md +122 -2
- package/src/DeepLinkIapProvider.tsx +105 -1
- package/src/useDeepLinkIapProvider.tsx +4 -2
|
@@ -16,6 +16,7 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
16
16
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
17
17
|
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void | string>;
|
|
18
18
|
initialize: (code: string | null, verboseLogging?: boolean) => Promise<void>;
|
|
19
|
+
fetchAndConditionallyOpenUrl: (affiliateIdentifier: string, offerCodeUrlId: string) => Promise<boolean>;
|
|
19
20
|
isInitialized: boolean;
|
|
20
21
|
};
|
|
21
22
|
export declare const DeepLinkIapContext: React.Context<T_DEEPLINK_IAP_CONTEXT>;
|
|
@@ -59,6 +59,7 @@ exports.DeepLinkIapContext = (0, react_1.createContext)({
|
|
|
59
59
|
setShortCode: (shortCode) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
60
60
|
setInsertAffiliateIdentifier: (referringLink) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
61
61
|
initialize: (code, verboseLogging) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
62
|
+
fetchAndConditionallyOpenUrl: (affiliateIdentifier, offerCodeUrlId) => __awaiter(void 0, void 0, void 0, function* () { return false; }),
|
|
62
63
|
isInitialized: false,
|
|
63
64
|
});
|
|
64
65
|
const DeepLinkIapProvider = ({ children, }) => {
|
|
@@ -529,6 +530,87 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
529
530
|
return Promise.reject(error);
|
|
530
531
|
}
|
|
531
532
|
});
|
|
533
|
+
const fetchAndConditionallyOpenUrl = (affiliateIdentifier, offerCodeUrlId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
534
|
+
try {
|
|
535
|
+
verboseLog(`Attempting to fetch and conditionally open URL for affiliate: ${affiliateIdentifier}, offerCodeUrlId: ${offerCodeUrlId}`);
|
|
536
|
+
if (react_native_1.Platform.OS !== 'ios') {
|
|
537
|
+
console.warn("[Insert Affiliate] Offer codes are only supported on iOS");
|
|
538
|
+
verboseLog("Offer codes are only supported on iOS");
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
const offerCode = yield fetchOfferCode(affiliateIdentifier);
|
|
542
|
+
if (offerCode && offerCode.length > 0) {
|
|
543
|
+
yield openRedeemURL(offerCode, offerCodeUrlId);
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
verboseLog("No valid offer code found");
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
console.error('[Insert Affiliate] Error fetching and opening offer code URL:', error);
|
|
553
|
+
verboseLog(`Error fetching and opening offer code URL: ${error}`);
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
const fetchOfferCode = (affiliateLink) => __awaiter(void 0, void 0, void 0, function* () {
|
|
558
|
+
try {
|
|
559
|
+
const encodedAffiliateLink = encodeURIComponent(affiliateLink);
|
|
560
|
+
const url = `https://api.insertaffiliate.com/v1/affiliateReturnOfferCode/${encodedAffiliateLink}`;
|
|
561
|
+
verboseLog(`Fetching offer code from: ${url}`);
|
|
562
|
+
const response = yield axios_1.default.get(url);
|
|
563
|
+
if (response.status === 200) {
|
|
564
|
+
const offerCode = response.data;
|
|
565
|
+
// Check for specific error strings from API
|
|
566
|
+
if (typeof offerCode === 'string' && (offerCode.includes("errorofferCodeNotFound") ||
|
|
567
|
+
offerCode.includes("errorAffiliateoffercodenotfoundinanycompany") ||
|
|
568
|
+
offerCode.includes("errorAffiliateoffercodenotfoundinanycompanyAffiliatelinkwas") ||
|
|
569
|
+
offerCode.includes("Routenotfound"))) {
|
|
570
|
+
console.warn(`[Insert Affiliate] Offer code not found or invalid: ${offerCode}`);
|
|
571
|
+
verboseLog(`Offer code not found or invalid: ${offerCode}`);
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
const cleanedOfferCode = cleanOfferCode(offerCode);
|
|
575
|
+
verboseLog(`Successfully fetched and cleaned offer code: ${cleanedOfferCode}`);
|
|
576
|
+
return cleanedOfferCode;
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
console.error(`[Insert Affiliate] Failed to fetch offer code. Status code: ${response.status}, Response: ${JSON.stringify(response.data)}`);
|
|
580
|
+
verboseLog(`Failed to fetch offer code. Status code: ${response.status}, Response: ${JSON.stringify(response.data)}`);
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
catch (error) {
|
|
585
|
+
console.error('[Insert Affiliate] Error fetching offer code:', error);
|
|
586
|
+
verboseLog(`Error fetching offer code: ${error}`);
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
const openRedeemURL = (offerCode, offerCodeUrlId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
591
|
+
try {
|
|
592
|
+
const redeemUrl = `https://apps.apple.com/redeem?ctx=offercodes&id=${offerCodeUrlId}&code=${offerCode}`;
|
|
593
|
+
verboseLog(`Opening redeem URL: ${redeemUrl}`);
|
|
594
|
+
const canOpen = yield react_native_1.Linking.canOpenURL(redeemUrl);
|
|
595
|
+
if (canOpen) {
|
|
596
|
+
yield react_native_1.Linking.openURL(redeemUrl);
|
|
597
|
+
console.log('[Insert Affiliate] Successfully opened redeem URL');
|
|
598
|
+
verboseLog('Successfully opened redeem URL');
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
console.error(`[Insert Affiliate] Could not launch redeem URL: ${redeemUrl}`);
|
|
602
|
+
verboseLog(`Could not launch redeem URL: ${redeemUrl}`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
console.error('[Insert Affiliate] Error opening redeem URL:', error);
|
|
607
|
+
verboseLog(`Error opening redeem URL: ${error}`);
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
const cleanOfferCode = (offerCode) => {
|
|
611
|
+
// Remove special characters, keep only alphanumeric
|
|
612
|
+
return offerCode.replace(/[^a-zA-Z0-9]/g, '');
|
|
613
|
+
};
|
|
532
614
|
return (react_1.default.createElement(exports.DeepLinkIapContext.Provider, { value: {
|
|
533
615
|
referrerLink,
|
|
534
616
|
userId,
|
|
@@ -541,6 +623,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
541
623
|
setInsertAffiliateIdentifier,
|
|
542
624
|
initialize,
|
|
543
625
|
isInitialized,
|
|
626
|
+
fetchAndConditionallyOpenUrl,
|
|
544
627
|
} }, children));
|
|
545
628
|
};
|
|
546
629
|
exports.default = DeepLinkIapProvider;
|
|
@@ -12,5 +12,6 @@ declare const useDeepLinkIapProvider: () => {
|
|
|
12
12
|
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void | string>;
|
|
13
13
|
initialize: (code: string | null, verboseLogging?: boolean) => Promise<void>;
|
|
14
14
|
isInitialized: boolean;
|
|
15
|
+
fetchAndConditionallyOpenUrl: (affiliateIdentifier: string, offerCodeUrlId: string) => Promise<boolean>;
|
|
15
16
|
};
|
|
16
17
|
export default useDeepLinkIapProvider;
|
|
@@ -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 } = (0, react_1.useContext)(DeepLinkIapProvider_1.DeepLinkIapContext);
|
|
6
|
+
const { referrerLink, userId, validatePurchaseWithIapticAPI, storeExpectedStoreTransaction, returnUserAccountTokenAndStoreExpectedTransaction, returnInsertAffiliateIdentifier, trackEvent, setShortCode, setInsertAffiliateIdentifier, initialize, isInitialized, fetchAndConditionallyOpenUrl } = (0, react_1.useContext)(DeepLinkIapProvider_1.DeepLinkIapContext);
|
|
7
7
|
return {
|
|
8
8
|
referrerLink,
|
|
9
9
|
userId,
|
|
@@ -15,7 +15,8 @@ const useDeepLinkIapProvider = () => {
|
|
|
15
15
|
setShortCode,
|
|
16
16
|
setInsertAffiliateIdentifier,
|
|
17
17
|
initialize,
|
|
18
|
-
isInitialized
|
|
18
|
+
isInitialized,
|
|
19
|
+
fetchAndConditionallyOpenUrl
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
22
|
exports.default = useDeepLinkIapProvider;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -498,7 +498,7 @@ At this stage, we cannot guarantee that this feature is fully resistant to tampe
|
|
|
498
498
|
|
|
499
499
|
#### Using `trackEvent`
|
|
500
500
|
|
|
501
|
-
To track an event, use the `trackEvent` function. Make sure to set an affiliate identifier first; otherwise, event tracking won
|
|
501
|
+
To track an event, use the `trackEvent` function. Make sure to set an affiliate identifier first; otherwise, event tracking won't work. Here's an example:
|
|
502
502
|
|
|
503
503
|
```javascript
|
|
504
504
|
const {
|
|
@@ -520,7 +520,127 @@ const {
|
|
|
520
520
|
/>
|
|
521
521
|
```
|
|
522
522
|
|
|
523
|
-
### 2.
|
|
523
|
+
### 2. Offer Codes
|
|
524
|
+
|
|
525
|
+
Offer Codes allow you to automatically present a discount to users who access an affiliate's link or enter a short code. This provides affiliates with a compelling incentive to promote your app, as discounts are automatically applied during the redemption flow [(learn more)](https://docs.insertaffiliate.com/offer-codes).
|
|
526
|
+
|
|
527
|
+
**Note: Offer Codes are currently only supported on iOS.**
|
|
528
|
+
|
|
529
|
+
You'll need your Offer Code URL ID, which can be created and retrieved from App Store Connect. Instructions to retrieve your Offer Code URL ID are available [here](https://docs.insertaffiliate.com/offer-codes#create-the-codes-within-app-store-connect).
|
|
530
|
+
|
|
531
|
+
To fetch an Offer Code and conditionally redirect the user to redeem it, pass the affiliate identifier (deep link or short code) to:
|
|
532
|
+
|
|
533
|
+
```javascript
|
|
534
|
+
const { fetchAndConditionallyOpenUrl } = useDeepLinkIapProvider();
|
|
535
|
+
|
|
536
|
+
await fetchAndConditionallyOpenUrl("your_affiliate_identifier", "your_offer_code_url_id");
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
#### Branch.io Example
|
|
540
|
+
|
|
541
|
+
```javascript
|
|
542
|
+
import React, { useEffect } from 'react';
|
|
543
|
+
import branch from 'react-native-branch';
|
|
544
|
+
import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
545
|
+
|
|
546
|
+
const DeepLinkHandler = () => {
|
|
547
|
+
const { fetchAndConditionallyOpenUrl } = useDeepLinkIapProvider();
|
|
548
|
+
|
|
549
|
+
useEffect(() => {
|
|
550
|
+
const branchSubscription = branch.subscribe(async ({ error, params }) => {
|
|
551
|
+
if (error) {
|
|
552
|
+
console.error('Error from Branch:', error);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (params['+clicked_branch_link']) {
|
|
557
|
+
const referringLink = params['~referring_link'];
|
|
558
|
+
if (referringLink) {
|
|
559
|
+
try {
|
|
560
|
+
await fetchAndConditionallyOpenUrl(
|
|
561
|
+
referringLink,
|
|
562
|
+
"{{ your_offer_code_url_id }}"
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
// Other code required for Insert Affiliate in the other listed steps...
|
|
566
|
+
} catch (err) {
|
|
567
|
+
console.error('Error with offer code:', err);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
return () => branchSubscription();
|
|
574
|
+
}, [fetchAndConditionallyOpenUrl]);
|
|
575
|
+
|
|
576
|
+
return <App />;
|
|
577
|
+
};
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
#### Short Code Example
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
import React, { useState } from 'react';
|
|
584
|
+
import { View, TextInput, Button, StyleSheet } from 'react-native';
|
|
585
|
+
import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
586
|
+
|
|
587
|
+
const ShortCodeInputWidget = () => {
|
|
588
|
+
const [shortCode, setShortCode] = useState('');
|
|
589
|
+
const { setShortCode: setInsertAffiliateShortCode, fetchAndConditionallyOpenUrl } = useDeepLinkIapProvider();
|
|
590
|
+
|
|
591
|
+
const handleShortCodeSubmission = async () => {
|
|
592
|
+
const trimmedCode = shortCode.trim();
|
|
593
|
+
|
|
594
|
+
if (trimmedCode.length > 0) {
|
|
595
|
+
try {
|
|
596
|
+
// Set the short code for affiliate tracking
|
|
597
|
+
await setInsertAffiliateShortCode(trimmedCode);
|
|
598
|
+
|
|
599
|
+
// Fetch and conditionally open offer code URL
|
|
600
|
+
await fetchAndConditionallyOpenUrl(
|
|
601
|
+
trimmedCode,
|
|
602
|
+
"{{ your_offer_code_url_id }}"
|
|
603
|
+
);
|
|
604
|
+
} catch (error) {
|
|
605
|
+
console.error('Error handling short code:', error);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
return (
|
|
611
|
+
<View style={styles.container}>
|
|
612
|
+
<TextInput
|
|
613
|
+
style={styles.input}
|
|
614
|
+
value={shortCode}
|
|
615
|
+
onChangeText={setShortCode}
|
|
616
|
+
placeholder="Enter your code"
|
|
617
|
+
placeholderTextColor="#ABC123"
|
|
618
|
+
/>
|
|
619
|
+
<Button
|
|
620
|
+
title="Apply Code"
|
|
621
|
+
onPress={handleShortCodeSubmission}
|
|
622
|
+
/>
|
|
623
|
+
</View>
|
|
624
|
+
);
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const styles = StyleSheet.create({
|
|
628
|
+
container: {
|
|
629
|
+
padding: 20,
|
|
630
|
+
},
|
|
631
|
+
input: {
|
|
632
|
+
borderWidth: 1,
|
|
633
|
+
borderColor: '#ddd',
|
|
634
|
+
padding: 10,
|
|
635
|
+
marginBottom: 10,
|
|
636
|
+
borderRadius: 5,
|
|
637
|
+
},
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
export default ShortCodeInputWidget;
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### 3. Short Codes (Beta)
|
|
524
644
|
|
|
525
645
|
#### What are Short Codes?
|
|
526
646
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { createContext, useEffect, useState } from 'react';
|
|
2
|
-
import { Platform } from 'react-native';
|
|
2
|
+
import { Platform, Linking } from 'react-native';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
5
5
|
|
|
@@ -32,6 +32,10 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
32
32
|
referringLink: string
|
|
33
33
|
) => Promise<void | string>;
|
|
34
34
|
initialize: (code: string | null, verboseLogging?: boolean) => Promise<void>;
|
|
35
|
+
fetchAndConditionallyOpenUrl: (
|
|
36
|
+
affiliateIdentifier: string,
|
|
37
|
+
offerCodeUrlId: string
|
|
38
|
+
) => Promise<boolean>;
|
|
35
39
|
isInitialized: boolean;
|
|
36
40
|
};
|
|
37
41
|
|
|
@@ -76,6 +80,10 @@ export const DeepLinkIapContext = createContext<T_DEEPLINK_IAP_CONTEXT>({
|
|
|
76
80
|
setShortCode: async (shortCode: string) => {},
|
|
77
81
|
setInsertAffiliateIdentifier: async (referringLink: string) => {},
|
|
78
82
|
initialize: async (code: string | null, verboseLogging?: boolean) => {},
|
|
83
|
+
fetchAndConditionallyOpenUrl: async (
|
|
84
|
+
affiliateIdentifier: string,
|
|
85
|
+
offerCodeUrlId: string
|
|
86
|
+
) => false,
|
|
79
87
|
isInitialized: false,
|
|
80
88
|
});
|
|
81
89
|
|
|
@@ -638,6 +646,101 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
638
646
|
}
|
|
639
647
|
};
|
|
640
648
|
|
|
649
|
+
const fetchAndConditionallyOpenUrl = async (
|
|
650
|
+
affiliateIdentifier: string,
|
|
651
|
+
offerCodeUrlId: string
|
|
652
|
+
): Promise<boolean> => {
|
|
653
|
+
try {
|
|
654
|
+
verboseLog(`Attempting to fetch and conditionally open URL for affiliate: ${affiliateIdentifier}, offerCodeUrlId: ${offerCodeUrlId}`);
|
|
655
|
+
|
|
656
|
+
if (Platform.OS !== 'ios') {
|
|
657
|
+
console.warn("[Insert Affiliate] Offer codes are only supported on iOS");
|
|
658
|
+
verboseLog("Offer codes are only supported on iOS");
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const offerCode = await fetchOfferCode(affiliateIdentifier);
|
|
663
|
+
|
|
664
|
+
if (offerCode && offerCode.length > 0) {
|
|
665
|
+
await openRedeemURL(offerCode, offerCodeUrlId);
|
|
666
|
+
return true;
|
|
667
|
+
} else {
|
|
668
|
+
verboseLog("No valid offer code found");
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
} catch (error) {
|
|
672
|
+
console.error('[Insert Affiliate] Error fetching and opening offer code URL:', error);
|
|
673
|
+
verboseLog(`Error fetching and opening offer code URL: ${error}`);
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const fetchOfferCode = async (affiliateLink: string): Promise<string | null> => {
|
|
679
|
+
try {
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
const encodedAffiliateLink = encodeURIComponent(affiliateLink);
|
|
683
|
+
const url = `https://api.insertaffiliate.com/v1/affiliateReturnOfferCode/${encodedAffiliateLink}`;
|
|
684
|
+
|
|
685
|
+
verboseLog(`Fetching offer code from: ${url}`);
|
|
686
|
+
|
|
687
|
+
const response = await axios.get(url);
|
|
688
|
+
|
|
689
|
+
if (response.status === 200) {
|
|
690
|
+
const offerCode = response.data;
|
|
691
|
+
|
|
692
|
+
// Check for specific error strings from API
|
|
693
|
+
if (typeof offerCode === 'string' && (
|
|
694
|
+
offerCode.includes("errorofferCodeNotFound") ||
|
|
695
|
+
offerCode.includes("errorAffiliateoffercodenotfoundinanycompany") ||
|
|
696
|
+
offerCode.includes("errorAffiliateoffercodenotfoundinanycompanyAffiliatelinkwas") ||
|
|
697
|
+
offerCode.includes("Routenotfound")
|
|
698
|
+
)) {
|
|
699
|
+
console.warn(`[Insert Affiliate] Offer code not found or invalid: ${offerCode}`);
|
|
700
|
+
verboseLog(`Offer code not found or invalid: ${offerCode}`);
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const cleanedOfferCode = cleanOfferCode(offerCode);
|
|
705
|
+
verboseLog(`Successfully fetched and cleaned offer code: ${cleanedOfferCode}`);
|
|
706
|
+
return cleanedOfferCode;
|
|
707
|
+
} else {
|
|
708
|
+
console.error(`[Insert Affiliate] Failed to fetch offer code. Status code: ${response.status}, Response: ${JSON.stringify(response.data)}`);
|
|
709
|
+
verboseLog(`Failed to fetch offer code. Status code: ${response.status}, Response: ${JSON.stringify(response.data)}`);
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
712
|
+
} catch (error) {
|
|
713
|
+
console.error('[Insert Affiliate] Error fetching offer code:', error);
|
|
714
|
+
verboseLog(`Error fetching offer code: ${error}`);
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
const openRedeemURL = async (offerCode: string, offerCodeUrlId: string): Promise<void> => {
|
|
720
|
+
try {
|
|
721
|
+
const redeemUrl = `https://apps.apple.com/redeem?ctx=offercodes&id=${offerCodeUrlId}&code=${offerCode}`;
|
|
722
|
+
verboseLog(`Opening redeem URL: ${redeemUrl}`);
|
|
723
|
+
|
|
724
|
+
const canOpen = await Linking.canOpenURL(redeemUrl);
|
|
725
|
+
if (canOpen) {
|
|
726
|
+
await Linking.openURL(redeemUrl);
|
|
727
|
+
console.log('[Insert Affiliate] Successfully opened redeem URL');
|
|
728
|
+
verboseLog('Successfully opened redeem URL');
|
|
729
|
+
} else {
|
|
730
|
+
console.error(`[Insert Affiliate] Could not launch redeem URL: ${redeemUrl}`);
|
|
731
|
+
verboseLog(`Could not launch redeem URL: ${redeemUrl}`);
|
|
732
|
+
}
|
|
733
|
+
} catch (error) {
|
|
734
|
+
console.error('[Insert Affiliate] Error opening redeem URL:', error);
|
|
735
|
+
verboseLog(`Error opening redeem URL: ${error}`);
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
const cleanOfferCode = (offerCode: string): string => {
|
|
740
|
+
// Remove special characters, keep only alphanumeric
|
|
741
|
+
return offerCode.replace(/[^a-zA-Z0-9]/g, '');
|
|
742
|
+
};
|
|
743
|
+
|
|
641
744
|
return (
|
|
642
745
|
<DeepLinkIapContext.Provider
|
|
643
746
|
value={{
|
|
@@ -652,6 +755,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
652
755
|
setInsertAffiliateIdentifier,
|
|
653
756
|
initialize,
|
|
654
757
|
isInitialized,
|
|
758
|
+
fetchAndConditionallyOpenUrl,
|
|
655
759
|
}}
|
|
656
760
|
>
|
|
657
761
|
{children}
|
|
@@ -13,7 +13,8 @@ const useDeepLinkIapProvider = () => {
|
|
|
13
13
|
setShortCode,
|
|
14
14
|
setInsertAffiliateIdentifier,
|
|
15
15
|
initialize,
|
|
16
|
-
isInitialized
|
|
16
|
+
isInitialized,
|
|
17
|
+
fetchAndConditionallyOpenUrl
|
|
17
18
|
} = useContext(DeepLinkIapContext);
|
|
18
19
|
|
|
19
20
|
return {
|
|
@@ -27,7 +28,8 @@ const useDeepLinkIapProvider = () => {
|
|
|
27
28
|
setShortCode,
|
|
28
29
|
setInsertAffiliateIdentifier,
|
|
29
30
|
initialize,
|
|
30
|
-
isInitialized
|
|
31
|
+
isInitialized,
|
|
32
|
+
fetchAndConditionallyOpenUrl
|
|
31
33
|
};
|
|
32
34
|
};
|
|
33
35
|
|