{"id":878,"date":"2026-04-22T13:00:00","date_gmt":"2026-04-22T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=878"},"modified":"2026-03-07T03:48:31","modified_gmt":"2026-03-07T08:48:31","slug":"testing-after-migration","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/testing-after-migration\/","title":{"rendered":"Testing After Migration: Verification Guide"},"content":{"rendered":"\n<p>Migrating deep linking platforms is only half the work. The other half is verifying everything works. A missed edge case during testing means a broken link in production, which means lost users and a support ticket you could have avoided.<\/p>\n\n\n\n<p>This guide covers every test you should run after migrating your deep linking platform, organized by priority.<\/p>\n\n\n\n<p>For the migration checklist, see <a href=\"https:\/\/tolinku.com\/blog\/deep-linking-migration-checklist\/\">Deep Linking Migration Checklist: 30 Steps<\/a>. For troubleshooting, see the <a href=\"https:\/\/tolinku.com\/docs\/troubleshooting\/common-issues\/\">Tolinku troubleshooting guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 1: Link Resolution<\/h2>\n\n\n\n<p>The most basic test: do your links actually work?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Click-to-Web Fallback<\/h3>\n\n\n\n<p>Open each link in a browser where the app is not installed. The link should redirect to the correct web fallback URL.<\/p>\n\n\n\n<p><strong>What to check:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The redirect happens (no error page, no timeout)<\/li>\n<li>The destination URL is correct (not a generic homepage if a specific page was expected)<\/li>\n<li>HTTPS is enforced (no mixed content or certificate warnings)<\/li>\n<li>Query parameters are preserved through the redirect<\/li>\n<\/ul>\n\n\n\n<p><strong>How to test:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Desktop browser (Chrome, Safari, Firefox)<\/li>\n<li>Mobile browser (Safari on iOS, Chrome on Android) without the app installed<\/li>\n<li>Use incognito\/private mode to avoid caching<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Click-to-App (Direct Deep Link)<\/h3>\n\n\n\n<p>With the app installed, tap a link. The app should open and navigate to the correct screen.<\/p>\n\n\n\n<p><strong>What to check:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The app opens (not the App Store or Play Store)<\/li>\n<li>The correct screen loads (not the home screen)<\/li>\n<li>Parameters are passed correctly (product ID, referral code, etc.)<\/li>\n<li>The app handles the link within 1-2 seconds (no long loading state)<\/li>\n<\/ul>\n\n\n\n<p><strong>How to test on iOS:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Paste a link in Notes, long-press, and tap &quot;Open&quot;<\/li>\n<li>Send the link via iMessage and tap it<\/li>\n<li>Paste it in Safari and navigate to it (note: typing a URL in Safari&#39;s address bar does NOT trigger Universal Links; you must navigate from another app or tap a link)<\/li>\n<\/ul>\n\n\n\n<p><strong>How to test on Android:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Paste a link in a text message and tap it<\/li>\n<li>Use <code>adb shell am start -a android.intent.action.VIEW -d &quot;https:\/\/go.yourapp.com\/test&quot;<\/code> from terminal<\/li>\n<li>Share the link from Chrome to verify intent resolution<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 2: Universal Links and App Links Verification<\/h2>\n\n\n\n<p>These are the configuration files that tell iOS and Android which links your app handles.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Apple App Site Association (AASA) File<\/h3>\n\n\n\n<p>The AASA file must be served from your domain at <code>\/.well-known\/apple-app-site-association<\/code>.<\/p>\n\n\n\n<p><strong>Verify the file is accessible:<\/strong><\/p>\n\n\n\n<pre><code class=\"language-bash\">curl -I https:\/\/go.yourapp.com\/.well-known\/apple-app-site-association\n<\/code><\/pre>\n\n\n\n<p>The response should return:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>HTTP 200 status<\/li>\n<li><code>Content-Type: application\/json<\/code><\/li>\n<li>Valid JSON content with your app&#39;s Team ID and Bundle ID<\/li>\n<\/ul>\n\n\n\n<p><strong>Verify the content:<\/strong><\/p>\n\n\n\n<pre><code class=\"language-bash\">curl https:\/\/go.yourapp.com\/.well-known\/apple-app-site-association | python3 -m json.tool\n<\/code><\/pre>\n\n\n\n<p>Check that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>applinks.details<\/code> contains your app&#39;s identifier (<code>TEAMID.com.yourapp.bundleid<\/code>)<\/li>\n<li>The path patterns match your routes (<code>\/product\/*<\/code>, <code>\/invite\/*<\/code>, etc.)<\/li>\n<li>There are no wildcard-only patterns that could interfere with other paths<\/li>\n<\/ul>\n\n\n\n<p><strong>Apple&#39;s CDN validation:<\/strong>\nApple caches AASA files through their CDN. After migration, verify Apple has picked up the new file:<\/p>\n\n\n\n<pre><code class=\"language-bash\">curl &quot;https:\/\/app-site-association.cdn-apple.com\/a\/v1\/go.yourapp.com&quot;\n<\/code><\/pre>\n\n\n\n<p>If the cached version is stale, it can take 24-48 hours for Apple to re-fetch. You can force a refresh by opening <a href=\"https:\/\/search.developer.apple.com\/appsearch-validation-tool\/\" rel=\"nofollow noopener\" target=\"_blank\">Apple&#39;s search validation tool<\/a> and entering your domain.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Android assetlinks.json<\/h3>\n\n\n\n<p>The Digital Asset Links file must be served at <code>\/.well-known\/assetlinks.json<\/code>.<\/p>\n\n\n\n<p><strong>Verify:<\/strong><\/p>\n\n\n\n<pre><code class=\"language-bash\">curl https:\/\/go.yourapp.com\/.well-known\/assetlinks.json | python3 -m json.tool\n<\/code><\/pre>\n\n\n\n<p>Check that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>target.package_name<\/code> matches your Android app&#39;s package name<\/li>\n<li>The <code>sha256_cert_fingerprints<\/code> includes your signing certificate&#39;s fingerprint<\/li>\n<li>If you use Google Play App Signing, include both your upload key AND Google&#39;s signing key fingerprint<\/li>\n<\/ul>\n\n\n\n<p><strong>Google&#39;s verification tool:<\/strong>\nUse <a href=\"https:\/\/developers.google.com\/digital-asset-links\/tools\/generator\" rel=\"nofollow noopener\" target=\"_blank\">Google&#39;s Digital Asset Links tool<\/a> to verify your assetlinks.json is configured correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 3: Deferred Deep Linking<\/h2>\n\n\n\n<p>Deferred deep linking is the hardest to test because it requires a full install cycle.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Test Process<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Uninstall the app from your test device<\/li>\n<li>Clear any cookies or cached data from the browser<\/li>\n<li>Tap a deep link (e.g., <code>https:\/\/go.yourapp.com\/product\/123<\/code>)<\/li>\n<li>You should be redirected to the App Store or Play Store<\/li>\n<li>Install the app<\/li>\n<li>Open the app<\/li>\n<li>The app should navigate to the correct screen (e.g., product 123)<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">What Can Go Wrong<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Fingerprinting mismatch<\/strong>: The platform uses device fingerprinting (IP, user agent, device model) to match the click to the install. If you&#39;re on a VPN or your IP changed between click and install, the match may fail.<\/li>\n<li><strong>Time window expired<\/strong>: Most platforms have a matching window (30 minutes to 24 hours). If you wait too long between clicking and installing, the match expires.<\/li>\n<li><strong>App not checking on first launch<\/strong>: Your app needs to call the deferred deep link check on first launch. If the SDK initialization is delayed or the check is missing, the link data won&#39;t be retrieved.<\/li>\n<li><strong>Test device already known<\/strong>: If the device previously had the app installed, some platforms may have cached state that interferes with deferred matching. Use a fresh device or clear all app data.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Testing Tips<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test on a physical device, not a simulator (fingerprinting relies on real device signals)<\/li>\n<li>Use a different network than your development machine to avoid IP-based false matches<\/li>\n<li>Test both iOS and Android separately<\/li>\n<li>Test with both the shortest and longest link formats<\/li>\n<\/ul>\n\n\n\n<p>For more testing tools and approaches, see <a href=\"https:\/\/tolinku.com\/blog\/deep-link-testing-tools\/\">Best Deep Link Testing Tools<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 4: Cross-Platform Behavior<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">iOS Specific<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Universal Links from different apps<\/strong>: Test links from Mail, Messages, Notes, Safari, Twitter, Slack. Each app handles Universal Links slightly differently.<\/li>\n<li><strong>Universal Links clipboard banner<\/strong>: When you copy a Universal Link and switch to Safari, iOS may show a banner suggesting to open the app. Verify this works.<\/li>\n<li><strong>Long-press behavior<\/strong>: Long-pressing a Universal Link should show &quot;Open in [App Name]&quot; in the context menu.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Android Specific<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>App Links auto-verification<\/strong>: After install, Android verifies your domain ownership. Check that your app is set as the default handler: Settings \u2192 Apps \u2192 [Your App] \u2192 Open by default \u2192 Supported links.<\/li>\n<li><strong>Intent filter conflicts<\/strong>: If another app on the device claims the same domain, Android may show a disambiguation dialog. Verify your app is the only one claiming your deep link domain.<\/li>\n<li><strong>Chrome behavior<\/strong>: Chrome handles App Links differently from other browsers. Specifically test links from within Chrome.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Cross-Platform<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Same link, both platforms<\/strong>: Send the same link to an iOS device and an Android device. Both should open the app and navigate to the same screen.<\/li>\n<li><strong>Desktop fallback<\/strong>: Open the link on a desktop browser. It should redirect to your web fallback, not show an error or try to open an app.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 5: Analytics and Tracking<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Click Tracking<\/h3>\n\n\n\n<p>After clicking test links, verify that clicks appear in your new platform&#39;s analytics dashboard.<\/p>\n\n\n\n<p><strong>What to check:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clicks are recorded with the correct timestamp<\/li>\n<li>Source information is captured (referrer, UTM parameters)<\/li>\n<li>Geographic data is recorded (country, region)<\/li>\n<li>Device information is captured (OS, browser, device type)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Conversion Tracking<\/h3>\n\n\n\n<p>If you track conversions (install, sign-up, purchase) through your deep linking platform:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Trigger a conversion through a tracked link<\/li>\n<li>Verify the conversion appears in the dashboard<\/li>\n<li>Verify the conversion is attributed to the correct link\/campaign<\/li>\n<li>Check that the time-to-convert metric is reasonable<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">UTM Parameter Passthrough<\/h3>\n\n\n\n<p>If your links include UTM parameters, verify they reach your analytics tool:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Click a link with UTM parameters: <code>https:\/\/go.yourapp.com\/page?utm_source=test&amp;utm_medium=email&amp;utm_campaign=migration_test<\/code><\/li>\n<li>Open the app or web page<\/li>\n<li>Check your analytics tool (Google Analytics, Mixpanel, etc.) for the session with those UTM values<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Priority 6: Edge Cases<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Malformed Links<\/h3>\n\n\n\n<p>Test links with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Missing parameters (<code>\/product\/<\/code> without an ID)<\/li>\n<li>Invalid parameters (<code>\/product\/not-a-number<\/code>)<\/li>\n<li>Extra path segments (<code>\/product\/123\/extra\/segments<\/code>)<\/li>\n<li>Special characters in parameters (<code>\/search?q=hello%20world&amp;lang=en<\/code>)<\/li>\n<li>Extremely long URLs<\/li>\n<\/ul>\n\n\n\n<p>The app should handle all of these gracefully: either navigate to a reasonable default or show an appropriate error. It should never crash.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Expired or Removed Links<\/h3>\n\n\n\n<p>If you delete a route on your new platform, what happens when someone clicks an old link that used that path? The platform should return a reasonable fallback (your default web URL), not a 500 error.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Rate Limiting<\/h3>\n\n\n\n<p>If your app generates links programmatically or receives high click volume, test under load:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create 100 links in quick succession via the API<\/li>\n<li>Click multiple links rapidly<\/li>\n<li>Verify no rate limiting issues or degraded performance<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Verification Checklist<\/h2>\n\n\n\n<p>Use this as a final sign-off before considering the migration complete:<\/p>\n\n\n\n<ul class=\"checklist wp-block-list\"><li><input type=\"checkbox\" disabled> <strong>AASA file<\/strong> accessible and valid at <code>\/.well-known\/apple-app-site-association<\/code><\/li><li><input type=\"checkbox\" disabled> <strong>assetlinks.json<\/strong> accessible and valid at <code>\/.well-known\/assetlinks.json<\/code><\/li><li><input type=\"checkbox\" disabled> <strong>Direct deep links work on iOS<\/strong> (app opens, correct screen)<\/li><li><input type=\"checkbox\" disabled> <strong>Direct deep links work on Android<\/strong> (app opens, correct screen)<\/li><li><input type=\"checkbox\" disabled> <strong>Deferred deep link works on iOS<\/strong> (install, first open, correct screen)<\/li><li><input type=\"checkbox\" disabled> <strong>Deferred deep link works on Android<\/strong> (install, first open, correct screen)<\/li><li><input type=\"checkbox\" disabled> <strong>Web fallback works<\/strong> (correct page, HTTPS, no errors)<\/li><li><input type=\"checkbox\" disabled> <strong>OG previews render<\/strong> on Facebook, Twitter, iMessage<\/li><li><input type=\"checkbox\" disabled> <strong>Analytics recording clicks<\/strong> in new platform dashboard<\/li><li><input type=\"checkbox\" disabled> <strong>UTM parameters passing through<\/strong> to analytics tools<\/li><li><input type=\"checkbox\" disabled> <strong>Edge cases handled gracefully<\/strong> (malformed, expired, missing params)<\/li><li><input type=\"checkbox\" disabled> <strong>All critical routes tested<\/strong> (product, invite, promo, etc.)<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Ongoing Monitoring<\/h2>\n\n\n\n<p>Testing is not a one-time event. After migration, monitor for 2-4 weeks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Click volume<\/strong>: Compare daily click counts to pre-migration baselines. A significant drop indicates broken links somewhere.<\/li>\n<li><strong>Deep link success rate<\/strong>: Track how often users land on the correct screen vs. the home screen.<\/li>\n<li><strong>User reports<\/strong>: Watch app store reviews and support channels for link-related complaints.<\/li>\n<li><strong>AASA\/assetlinks changes<\/strong>: If you update your app or domain configuration, re-run the verification checks.<\/li>\n<\/ul>\n\n\n\n<p>For the complete migration walkthrough, see <a href=\"https:\/\/tolinku.com\/blog\/migrating-to-tolinku\/\">Migrating to Tolinku from Branch, Firebase, and AppsFlyer<\/a>. For the SDK swap process, see <a href=\"https:\/\/tolinku.com\/blog\/sdk-swap-guide\/\">SDK Swap Guide<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Verify your deep linking works after platform migration. Test Universal Links, App Links, deferred links, and analytics across all channels.<\/p>\n","protected":false},"author":2,"featured_media":877,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Testing After Migration: Deep Link Verification Guide","rank_math_description":"Verify your deep linking works after platform migration. Test Universal Links, App Links, deferred links, and analytics across all channels.","rank_math_focus_keyword":"testing after migration","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-testing-after-migration.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-testing-after-migration.png","footnotes":""},"categories":[17],"tags":[25,23,20,21,24,52,80,22],"class_list":["post-878","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-comparisons","tag-android","tag-app-links","tag-deep-linking","tag-deferred-deep-linking","tag-ios","tag-migration","tag-testing","tag-universal-links"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/878","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=878"}],"version-history":[{"count":3,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/878\/revisions"}],"predecessor-version":[{"id":2519,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/878\/revisions\/2519"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/877"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}