From 3257030b087a1a8883c86c6d1a39971589d3b6d3 Mon Sep 17 00:00:00 2001 From: Elizabeth Bourke Date: Tue, 19 Aug 2025 12:32:09 +0100 Subject: [PATCH] Add comprehensive deep linking documentation for Cordova - Add DEEP_LINKING.md with complete setup guide for iOS and Android - Include practical examples with working JavaScript implementation - Add sample config.xml with proper plugin configuration - Provide interactive test page for validating deep links - Cover integration with Intercom messages, push notifications, and Help Center - Include troubleshooting guide and best practices - Address GitHub issue #387872 about missing deep linking documentation Files added: - DEEP_LINKING.md: Main documentation guide - examples/deep-linking-example.js: Complete JavaScript implementation - examples/config-example.xml: Sample Cordova configuration - examples/deep-link-test.html: Interactive test page - examples/README.md: Implementation guide with framework examples --- DEEP_LINKING.md | 309 +++++++++++++++++++++++++++ examples/README.md | 278 +++++++++++++++++++++++++ examples/config-example.xml | 182 ++++++++++++++++ examples/deep-link-test.html | 345 +++++++++++++++++++++++++++++++ examples/deep-linking-example.js | 342 ++++++++++++++++++++++++++++++ 5 files changed, 1456 insertions(+) create mode 100644 DEEP_LINKING.md create mode 100644 examples/README.md create mode 100644 examples/config-example.xml create mode 100644 examples/deep-link-test.html create mode 100644 examples/deep-linking-example.js diff --git a/DEEP_LINKING.md b/DEEP_LINKING.md new file mode 100644 index 0000000..c686739 --- /dev/null +++ b/DEEP_LINKING.md @@ -0,0 +1,309 @@ +# Deep Linking with Intercom for Cordova/PhoneGap + +This guide explains how to set up deep linking in your Cordova/PhoneGap app to work with Intercom messages, push notifications, and Help Center articles. + +## What is Deep Linking? + +Deep linking allows users to open your app directly to a specific screen or content using a custom URL scheme (e.g., `myapp://profile/123`). With Intercom, you can embed deep links in: + +- In-app messages +- Push notifications +- Help Center articles +- Email campaigns + +When users tap these links, they'll be taken directly to the relevant screen in your app instead of just opening the app's home screen. + +## Prerequisites + +- Cordova/PhoneGap app with Intercom plugin installed +- Basic understanding of Cordova configuration + +## Step 1: Install the Custom URL Scheme Plugin + +Install the Cordova Custom URL Scheme plugin to handle deep links: + +```bash +cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=myapp +``` + +Replace `myapp` with your desired URL scheme. Choose a unique scheme name that: +- Uses only lowercase characters +- Contains no spaces or special characters (except hyphens, which become underscores on Android) +- Doesn't conflict with existing schemes (fb, twitter, etc.) + +## Step 2: Configure Your App to Handle Deep Links + +### JavaScript Handler + +Add this function to your main JavaScript file (typically in `www/js/index.js`): + +```javascript +function handleOpenURL(url) { + console.log("Received deep link: " + url); + + // Wait for the app to be ready before processing the URL + document.addEventListener('deviceready', function() { + processDeepLink(url); + }, false); + + // If deviceready already fired, process immediately + if (window.cordova) { + processDeepLink(url); + } +} + +function processDeepLink(url) { + // Parse the URL to extract path and parameters + const urlParts = url.split('://'); + if (urlParts.length < 2) return; + + const scheme = urlParts[0]; // e.g., "myapp" + const pathAndQuery = urlParts[1]; // e.g., "profile/123?tab=settings" + + // Split path and query parameters + const [path, query] = pathAndQuery.split('?'); + const pathSegments = path.split('/').filter(segment => segment.length > 0); + + // Parse query parameters + const params = {}; + if (query) { + query.split('&').forEach(param => { + const [key, value] = param.split('='); + params[decodeURIComponent(key)] = decodeURIComponent(value || ''); + }); + } + + // Route to appropriate screen based on path + routeToScreen(pathSegments, params); +} + +function routeToScreen(pathSegments, params) { + // Example routing logic - customize based on your app structure + if (pathSegments.length === 0) { + // myapp:// - go to home + navigateToHome(); + } else if (pathSegments[0] === 'profile') { + // myapp://profile/123 + const userId = pathSegments[1]; + navigateToProfile(userId, params); + } else if (pathSegments[0] === 'product') { + // myapp://product/456?color=red + const productId = pathSegments[1]; + navigateToProduct(productId, params); + } else if (pathSegments[0] === 'support') { + // myapp://support - open Intercom + intercom.present(); + } + // Add more routing logic as needed +} + +// Example navigation functions - implement based on your app framework +function navigateToHome() { + // Navigate to home screen + console.log("Navigating to home"); +} + +function navigateToProfile(userId, params) { + // Navigate to profile screen + console.log("Navigating to profile:", userId, params); +} + +function navigateToProduct(productId, params) { + // Navigate to product screen + console.log("Navigating to product:", productId, params); +} +``` + +## Step 3: Platform-Specific Configuration + +### iOS Configuration + +The plugin automatically configures iOS, but you may need to add Universal Links support for better user experience. + +#### Universal Links (Recommended) + +1. Add your domain to `config.xml`: + +```xml + + + +``` + +2. Create an `apple-app-site-association` file on your web server at `https://myapp.com/.well-known/apple-app-site-association`: + +```json +{ + "applinks": { + "apps": [], + "details": [ + { + "appID": "TEAMID.com.yourcompany.yourapp", + "paths": ["/app/*", "/product/*", "/profile/*"] + } + ] + } +} +``` + +3. Handle Universal Links in your app: + +```javascript +// Universal Links are handled the same way as custom URL schemes +// The handleOpenURL function will be called automatically +``` + +### Android Configuration + +The plugin automatically adds the necessary intent filters to `AndroidManifest.xml`. For custom configuration, you can manually add: + +```xml + + + + + + + + +``` + +## Step 4: Using Deep Links with Intercom + +### In Push Notifications + +When creating push notifications in Intercom, set the URI field to your deep link: + +``` +myapp://product/123?source=push +``` + +### In In-App Messages + +Add deep links to your in-app message content: + +```html +Get Help +Update Profile +``` + +### In Help Center Articles + +Include deep links in your Help Center articles: + +```markdown +To view your order history, [click here](myapp://orders). +For account settings, [tap here](myapp://profile/settings). +``` + +## Step 5: Testing Deep Links + +### Testing on Device + +1. **iOS Simulator/Device**: Open Safari and type your deep link in the address bar: + ``` + myapp://profile/123 + ``` + +2. **Android Emulator/Device**: Use ADB to test: + ```bash + adb shell am start -W -a android.intent.action.VIEW -d "myapp://profile/123" com.yourcompany.yourapp + ``` + +3. **Create Test HTML Page**: + ```html + + + +

Deep Link Test

+ Open Profile
+ Open Product
+ Open Support + + + ``` + +### Testing with Intercom + +1. Create a test push notification with your deep link as the URI +2. Send yourself a test in-app message with deep link buttons +3. Add deep links to a test Help Center article + +## Common Issues and Solutions + +### handleOpenURL Not Called + +**Problem**: The `handleOpenURL` function isn't being called when the app opens. + +**Solutions**: +- Ensure the function is defined in the global scope +- Check that the URL scheme is correctly configured +- On iOS, verify the app isn't already running in the background + +### App Opens But Doesn't Navigate + +**Problem**: The app opens but doesn't navigate to the correct screen. + +**Solutions**: +- Add logging to debug the URL parsing +- Ensure your routing logic handles all expected URL formats +- Check that navigation functions are properly implemented + +### Android Intent Issues + +**Problem**: Deep links don't work on Android. + +**Solutions**: +- Verify the intent filter is correctly added to AndroidManifest.xml +- Set `android:launchMode="singleTask"` on your main activity +- Check for conflicts with other plugins + +## Best Practices + +1. **URL Structure**: Use a consistent, hierarchical URL structure: + ``` + myapp://section/item/action?param=value + ``` + +2. **Fallback Handling**: Always provide fallback behavior for unrecognized URLs: + ```javascript + function routeToScreen(pathSegments, params) { + // ... routing logic ... + + // Fallback to home if no route matches + navigateToHome(); + } + ``` + +3. **Parameter Validation**: Validate and sanitize URL parameters: + ```javascript + function navigateToProfile(userId, params) { + if (!userId || !userId.match(/^\d+$/)) { + console.error("Invalid user ID"); + navigateToHome(); + return; + } + // ... navigation logic ... + } + ``` + +4. **Analytics**: Track deep link usage for insights: + ```javascript + function processDeepLink(url) { + // Track deep link usage + intercom.logEvent('deep_link_opened', { url: url }); + + // ... rest of processing ... + } + ``` + +## Next Steps + +- Implement deep linking in your app using this guide +- Test thoroughly on both iOS and Android devices +- Create deep links in your Intercom messages and Help Center content +- Monitor deep link usage through analytics + +For more information about Intercom's deep linking capabilities, see: +- [iOS Deep Linking Documentation](https://developers.intercom.com/installing-intercom/ios/deep-linking) +- [Android Deep Linking Documentation](https://developers.intercom.com/installing-intercom/android/deep-linking) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..4460d64 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,278 @@ +# Deep Linking Examples for Cordova + Intercom + +This directory contains practical examples for implementing deep linking in Cordova apps with Intercom integration. + +## Files Overview + +### ๐Ÿ“„ `deep-linking-example.js` +Complete JavaScript implementation showing: +- Global `handleOpenURL` function +- URL parsing and routing logic +- Integration with Intercom events and content +- Error handling and fallbacks +- Example navigation functions + +### โš™๏ธ `config-example.xml` +Sample Cordova configuration file with: +- Intercom plugin configuration +- Custom URL scheme setup +- Platform-specific settings for iOS and Android +- Universal Links configuration +- Required permissions and preferences + +### ๐Ÿงช `deep-link-test.html` +Interactive test page for validating deep links: +- Clickable links for all supported URL patterns +- Visual feedback and URL display +- Mobile-optimized interface +- Testing instructions and commands + +## Quick Start + +### 1. Install Required Plugins + +```bash +# Install Intercom plugin +cordova plugin add cordova-plugin-intercom + +# Install Custom URL Scheme plugin (replace 'myshop' with your scheme) +cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=myshop +``` + +### 2. Configure Your App + +1. Copy the relevant sections from `config-example.xml` to your `config.xml` +2. Replace placeholder values with your actual Intercom credentials +3. Update the URL scheme to match your app + +### 3. Implement Deep Link Handling + +1. Copy `deep-linking-example.js` to your project +2. Include it in your main HTML file: + ```html + + ``` +3. Customize the routing logic for your app's navigation + +### 4. Test Your Implementation + +1. Host `deep-link-test.html` on a web server or open it locally +2. Access it from your mobile device +3. Click the test links to verify deep linking works + +## Supported URL Patterns + +The example implementation supports these URL patterns: + +### Basic Navigation +- `myshop://` โ†’ Home screen +- `myshop://profile` โ†’ User profile +- `myshop://orders` โ†’ Order history +- `myshop://cart` โ†’ Shopping cart + +### Product Pages +- `myshop://product/123` โ†’ Product detail page +- `myshop://product/123?highlight=reviews` โ†’ Product with specific section highlighted + +### Categories +- `myshop://category/electronics` โ†’ Category listing +- `myshop://category/clothing?filter=sale` โ†’ Filtered category + +### Support (Intercom Integration) +- `myshop://support` โ†’ Open Intercom messenger +- `myshop://support/article/456` โ†’ Open specific help article + +### Advanced Examples +- `myshop://profile?tab=settings` โ†’ Profile with specific tab +- `myshop://cart?promo=SAVE20` โ†’ Cart with promo code applied +- `myshop://orders?status=pending` โ†’ Filtered order list + +## Customization Guide + +### 1. Change URL Scheme + +Replace `myshop` with your app's scheme in: +- Plugin installation command +- `config.xml` configuration +- JavaScript URL parsing logic +- Test HTML file + +### 2. Add New Routes + +To add a new deep link pattern: + +1. **Update the routing function:** + ```javascript + function routeToScreen(parsedUrl) { + // Add your new route + if (path[0] === 'newroute') { + navigateToNewScreen(path[1], params); + } + } + ``` + +2. **Implement navigation function:** + ```javascript + function navigateToNewScreen(id, params) { + console.log("Navigating to new screen:", id, params); + // Your navigation logic here + } + ``` + +3. **Add test link to HTML:** + ```html + + New Screen +
myshop://newroute/123
+
+ ``` + +### 3. Integrate with Your Navigation Framework + +The examples use generic navigation functions. Replace them with your framework's methods: + +#### For Ionic/Angular: +```javascript +function navigateToProduct(productId, params) { + this.navCtrl.navigateForward(`/product/${productId}`, { + queryParams: params + }); +} +``` + +#### For React Native: +```javascript +function navigateToProduct(productId, params) { + navigation.navigate('Product', { + productId: productId, + ...params + }); +} +``` + +#### For Framework7: +```javascript +function navigateToProduct(productId, params) { + app.views.main.router.navigate(`/product/${productId}/`, { + props: params + }); +} +``` + +## Testing Commands + +### iOS Simulator +```bash +xcrun simctl openurl booted "myshop://product/123" +``` + +### Android Emulator/Device +```bash +adb shell am start -W -a android.intent.action.VIEW -d "myshop://product/123" com.example.myshop +``` + +### Browser Testing (Desktop) +Open the test HTML file and click the links. They won't open the app but will show the URL structure. + +## Troubleshooting + +### Deep Links Not Working + +1. **Check plugin installation:** + ```bash + cordova plugin list | grep customurlscheme + ``` + +2. **Verify URL scheme in config.xml:** + ```xml + + + + ``` + +3. **Ensure handleOpenURL is global:** + ```javascript + // Must be in global scope, not inside document.ready + function handleOpenURL(url) { + // Handler code + } + ``` + +### App Opens But Doesn't Navigate + +1. **Add debug logging:** + ```javascript + function processDeepLink(url) { + console.log("Processing deep link:", url); + // Add more logging throughout the function + } + ``` + +2. **Check device ready state:** + ```javascript + function handleOpenURL(url) { + console.log("Device ready:", !!window.cordova); + console.log("App ready:", !!window.appReady); + } + ``` + +### Android-Specific Issues + +1. **Check launch mode in AndroidManifest.xml:** + ```xml + + ``` + +2. **Verify intent filter:** + ```xml + + + + + + + ``` + +## Integration with Intercom + +### Creating Deep Links in Intercom + +1. **Push Notifications:** Set the URI field to your deep link +2. **In-App Messages:** Use HTML links in message content +3. **Help Center:** Add deep links to article content +4. **Email Campaigns:** Include deep links in email templates + +### Tracking Deep Link Usage + +The example includes Intercom event tracking: + +```javascript +// Track deep link opens +intercom.logEvent('deep_link_opened', { + url: url, + path: parsedUrl.path, + source: parsedUrl.params.source || 'unknown' +}); + +// Track specific actions +intercom.logEvent('product_viewed_via_deeplink', { + product_id: productId, + source: 'deep_link' +}); +``` + +## Best Practices + +1. **Always validate input:** Check URL parameters before using them +2. **Provide fallbacks:** Handle unknown URLs gracefully +3. **Track usage:** Monitor deep link performance with analytics +4. **Test thoroughly:** Verify on both iOS and Android devices +5. **Keep URLs simple:** Use clear, hierarchical URL structures +6. **Handle edge cases:** Account for app states and network conditions + +## Need Help? + +- Check the main [DEEP_LINKING.md](../DEEP_LINKING.md) documentation +- Review Intercom's platform-specific deep linking guides +- Test with the provided HTML test page +- Use browser developer tools to debug JavaScript issues diff --git a/examples/config-example.xml b/examples/config-example.xml new file mode 100644 index 0000000..a4bbbf2 --- /dev/null +++ b/examples/config-example.xml @@ -0,0 +1,182 @@ + + + MyShop + Example e-commerce app with Intercom deep linking + Example Team + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + applinks:myshop.com + applinks:www.myshop.com + + + + + applinks:myshop.com + applinks:www.myshop.com + + + + + + + remote-notification + + + + + + This app needs access to your photo library to send images in support messages. + + + + + This app needs access to your camera to take photos for support messages. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/deep-link-test.html b/examples/deep-link-test.html new file mode 100644 index 0000000..30f652e --- /dev/null +++ b/examples/deep-link-test.html @@ -0,0 +1,345 @@ + + + + + + Deep Link Test Page - MyShop App + + + +
+

๐Ÿ”— Deep Link Test Page

+

Test deep links for the MyShop Cordova app with Intercom integration

+ +
+ Instructions: +
    +
  1. Make sure the MyShop app is installed on your device
  2. +
  3. Click any link below to test deep linking
  4. +
  5. The app should open and navigate to the appropriate screen
  6. +
  7. If the app doesn't open, check the installation and URL scheme configuration
  8. +
+
+ +
+ Note: These links will only work if you have the MyShop app installed with the custom URL scheme "myshop://" configured. +
+ + + + + + + + + + + + + + + + + + + + +
+

๐Ÿ“ฒ Don't have the app installed?

+

Download the MyShop app from your device's app store:

+ +
+ + +
+

๐Ÿงช Testing Information

+

URL Scheme: myshop://

+

App Package: com.example.myshop

+

Supported Platforms: iOS 15+, Android API 22+

+ +

Manual Testing Commands:

+
+

iOS Simulator:

+ xcrun simctl openurl booted "myshop://product/123" + +

Android ADB:

+ adb shell am start -W -a android.intent.action.VIEW -d "myshop://product/123" com.example.myshop +
+
+
+ + + + diff --git a/examples/deep-linking-example.js b/examples/deep-linking-example.js new file mode 100644 index 0000000..0e349d1 --- /dev/null +++ b/examples/deep-linking-example.js @@ -0,0 +1,342 @@ +/** + * Deep Linking Example for Cordova + Intercom + * + * This example shows how to implement deep linking in a Cordova app + * that integrates with Intercom for customer support. + * + * URL Scheme: myshop:// + * + * Supported deep links: + * - myshop:// -> Home screen + * - myshop://product/123 -> Product detail page + * - myshop://category/electronics -> Category page + * - myshop://profile -> User profile + * - myshop://orders -> Order history + * - myshop://support -> Open Intercom + * - myshop://support/article/456 -> Open specific help article + * - myshop://cart?promo=SAVE20 -> Cart with promo code applied + */ + +// Global deep link handler - must be in global scope +function handleOpenURL(url) { + console.log("Deep link received: " + url); + + // Store the URL for processing after app is ready + window.pendingDeepLink = url; + + // If app is already ready, process immediately + if (window.appReady) { + processDeepLink(url); + } +} + +// App initialization +document.addEventListener('deviceready', function() { + console.log("Device ready"); + window.appReady = true; + + // Initialize Intercom + initializeIntercom(); + + // Process any pending deep link + if (window.pendingDeepLink) { + processDeepLink(window.pendingDeepLink); + window.pendingDeepLink = null; + } +}, false); + +function initializeIntercom() { + // Login user to Intercom (example with unidentified user) + intercom.loginUnidentifiedUser({}, + function() { + console.log("Intercom login successful"); + }, + function(error) { + console.error("Intercom login failed:", error); + } + ); +} + +function processDeepLink(url) { + try { + const parsedUrl = parseDeepLink(url); + + // Log deep link usage for analytics + intercom.logEvent('deep_link_opened', { + url: url, + path: parsedUrl.path, + source: parsedUrl.params.source || 'unknown' + }); + + // Route to appropriate screen + routeToScreen(parsedUrl); + + } catch (error) { + console.error("Error processing deep link:", error); + // Fallback to home screen + navigateToHome(); + } +} + +function parseDeepLink(url) { + // Parse URL: myshop://path/to/resource?param1=value1¶m2=value2 + const urlParts = url.split('://'); + if (urlParts.length < 2) { + throw new Error("Invalid URL format"); + } + + const scheme = urlParts[0]; // "myshop" + const pathAndQuery = urlParts[1]; // "path/to/resource?param1=value1" + + // Split path and query + const [fullPath, queryString] = pathAndQuery.split('?'); + const pathSegments = fullPath.split('/').filter(segment => segment.length > 0); + + // Parse query parameters + const params = {}; + if (queryString) { + queryString.split('&').forEach(param => { + const [key, value] = param.split('='); + if (key) { + params[decodeURIComponent(key)] = decodeURIComponent(value || ''); + } + }); + } + + return { + scheme: scheme, + path: pathSegments, + params: params, + fullPath: fullPath + }; +} + +function routeToScreen(parsedUrl) { + const path = parsedUrl.path; + const params = parsedUrl.params; + + if (path.length === 0) { + // myshop:// -> Home + navigateToHome(); + + } else if (path[0] === 'product' && path[1]) { + // myshop://product/123 + const productId = path[1]; + navigateToProduct(productId, params); + + } else if (path[0] === 'category' && path[1]) { + // myshop://category/electronics + const categoryName = path[1]; + navigateToCategory(categoryName, params); + + } else if (path[0] === 'profile') { + // myshop://profile + navigateToProfile(params); + + } else if (path[0] === 'orders') { + // myshop://orders + navigateToOrders(params); + + } else if (path[0] === 'cart') { + // myshop://cart?promo=SAVE20 + navigateToCart(params); + + } else if (path[0] === 'support') { + if (path[1] === 'article' && path[2]) { + // myshop://support/article/456 + const articleId = path[2]; + openIntercomArticle(articleId); + } else { + // myshop://support + openIntercomSupport(); + } + + } else { + // Unknown path - fallback to home + console.warn("Unknown deep link path:", path); + navigateToHome(); + } +} + +// Navigation functions - implement based on your app framework +function navigateToHome() { + console.log("Navigating to home screen"); + + // Example: If using a single-page app framework + // window.location.hash = '#/home'; + + // Example: If using a multi-page app + // window.location.href = 'index.html'; + + // Show success message + showToast("Welcome to MyShop!"); +} + +function navigateToProduct(productId, params) { + console.log("Navigating to product:", productId, params); + + // Validate product ID + if (!productId.match(/^\d+$/)) { + console.error("Invalid product ID:", productId); + navigateToHome(); + return; + } + + // Example navigation + // window.location.hash = '#/product/' + productId; + + // Apply any special parameters + if (params.highlight) { + // Highlight specific feature + console.log("Highlighting feature:", params.highlight); + } + + showToast("Opening product " + productId); +} + +function navigateToCategory(categoryName, params) { + console.log("Navigating to category:", categoryName, params); + + // Sanitize category name + const sanitizedCategory = categoryName.replace(/[^a-zA-Z0-9-_]/g, ''); + + // Example navigation + // window.location.hash = '#/category/' + sanitizedCategory; + + // Apply filters if provided + if (params.filter) { + console.log("Applying filter:", params.filter); + } + + showToast("Opening " + categoryName + " category"); +} + +function navigateToProfile(params) { + console.log("Navigating to profile", params); + + // Example navigation + // window.location.hash = '#/profile'; + + // Open specific tab if provided + if (params.tab) { + console.log("Opening tab:", params.tab); + // Example: openProfileTab(params.tab); + } + + showToast("Opening your profile"); +} + +function navigateToOrders(params) { + console.log("Navigating to orders", params); + + // Example navigation + // window.location.hash = '#/orders'; + + // Filter by status if provided + if (params.status) { + console.log("Filtering by status:", params.status); + } + + showToast("Opening your orders"); +} + +function navigateToCart(params) { + console.log("Navigating to cart", params); + + // Example navigation + // window.location.hash = '#/cart'; + + // Apply promo code if provided + if (params.promo) { + console.log("Applying promo code:", params.promo); + applyPromoCode(params.promo); + } + + showToast("Opening your cart"); +} + +function openIntercomSupport() { + console.log("Opening Intercom support"); + + // Open Intercom messenger + intercom.present(); + + // Log support access + intercom.logEvent('support_accessed', { + source: 'deep_link' + }); +} + +function openIntercomArticle(articleId) { + console.log("Opening Intercom article:", articleId); + + // Validate article ID + if (!articleId.match(/^\d+$/)) { + console.error("Invalid article ID:", articleId); + openIntercomSupport(); + return; + } + + // Open specific article + const article = intercomContent.articleWithArticleId(articleId); + intercom.presentContent(article); + + // Log article access + intercom.logEvent('help_article_opened', { + article_id: articleId, + source: 'deep_link' + }); +} + +// Utility functions +function applyPromoCode(promoCode) { + console.log("Applying promo code:", promoCode); + + // Example: Apply promo code to cart + // CartService.applyPromoCode(promoCode); + + // Show confirmation + showToast("Promo code " + promoCode + " applied!"); + + // Track promo usage + intercom.logEvent('promo_code_applied', { + promo_code: promoCode, + source: 'deep_link' + }); +} + +function showToast(message) { + // Simple toast implementation + console.log("Toast:", message); + + // Example: If using a UI framework with toast support + // UIFramework.showToast(message); + + // Fallback: Show alert (remove in production) + // alert(message); +} + +// Error handling for deep links +window.addEventListener('error', function(event) { + if (event.message && event.message.includes('deep link')) { + console.error("Deep link error:", event.error); + + // Log error to Intercom + intercom.logEvent('deep_link_error', { + error: event.message, + url: window.pendingDeepLink || 'unknown' + }); + + // Fallback to home + navigateToHome(); + } +}); + +// Export functions for testing (optional) +if (typeof module !== 'undefined' && module.exports) { + module.exports = { + parseDeepLink: parseDeepLink, + routeToScreen: routeToScreen, + processDeepLink: processDeepLink + }; +}