When a user taps an action in Storyteller that should route inside your app, subscribe to Storyteller.userNavigatedToApp.
import'dart:async';import'package:storyteller_sdk/storyteller_sdk.dart';latefinalStreamSubscription<String>_subscription;voidstartListeningToStorytellerLinks(){_subscription=Storyteller.userNavigatedToApp.listen((url){// Parse and route using your app's navigation system.// Example: myapp://product/123});}voidstopListeningToStorytellerLinks(){_subscription.cancel();}
If your app receives a URL (from your existing deep-link handling setup), you can forward Storyteller links to the SDK:
Check the URL with Storyteller.isStorytellerDeepLink(url)
If true, call Storyteller.openDeepLink(url)
import'package:storyteller_sdk/storyteller_sdk.dart';Future<void>handleIncomingUrl(Stringurl)async{if(awaitStoryteller.isStorytellerDeepLink(url)){awaitStoryteller.openDeepLink(url);return;}// Otherwise, handle it as your app's own deep link.}
The earlier isStorytellerDeeplink and openDeeplink spellings remain
source-compatible aliases; both pairs use the same native channel calls.
Storyteller.openClipByExternalId(...) and its
openCollectionByExternalId(...) alias
An explicit StorytellerOpenReason keeps analytics attribution consistent
when your app has already classified the navigation source. If you omit it,
the native entry point keeps its own default.
Android's external-ID Clips entry point always owns deep-link attribution. On
Android, omit openReason or pass StorytellerOpenReason.deeplink; passing
StorytellerOpenReason.instanceMethod throws an UNSUPPORTED_ARGUMENTPlatformException. iOS supports both reasons for the same Flutter API.
In the Showcase app, DeepLinkService._handleIncomingLink validates App Links, queues them until the SDK is ready, and finally calls Storyteller.openDeeplink—use it as a working template for production apps.
{"slug": "deeplinking", "page_title": "Deep Linking", "page_url": "Deeplinking/", "canonical_url": "/flutter/Deeplinking/", "markdown": "# Deep Linking\n\nDeep linking has two sides:\n\n1. **Opening Storyteller content from an incoming URL** (e.g. a user taps a Storyteller link and your app launches)\n2. **Navigating back to your app from Storyteller UI** (e.g. a Story page action button uses your app's URL scheme)\n\nThis page focuses on the Flutter SDK API surface. You still need the usual platform setup for app links/universal links on Android and iOS.\n\n## Navigate back to your app (`userNavigatedToApp`)\n\nWhen a user taps an action in Storyteller that should route inside your app, subscribe to `Storyteller.userNavigatedToApp`.\n\n```dart\nimport 'dart:async';\n\nimport 'package:storyteller_sdk/storyteller_sdk.dart';\n\nlate final StreamSubscription<String> _subscription;\n\nvoid startListeningToStorytellerLinks() {\n _subscription = Storyteller.userNavigatedToApp.listen((url) {\n // Parse and route using your app's navigation system.\n // Example: myapp://product/123\n });\n}\n\nvoid stopListeningToStorytellerLinks() {\n _subscription.cancel();\n}\n```\n\n## Handle incoming Storyteller deep links\n\nIf your app receives a URL (from your existing deep-link handling setup), you can forward Storyteller links to the SDK:\n\n1. Check the URL with `Storyteller.isStorytellerDeepLink(url)`\n2. If `true`, call `Storyteller.openDeepLink(url)`\n\n```dart\nimport 'package:storyteller_sdk/storyteller_sdk.dart';\n\nFuture<void> handleIncomingUrl(String url) async {\n if (await Storyteller.isStorytellerDeepLink(url)) {\n await Storyteller.openDeepLink(url);\n return;\n }\n\n // Otherwise, handle it as your app's own deep link.\n}\n```\n\nThe earlier `isStorytellerDeeplink` and `openDeeplink` spellings remain\nsource-compatible aliases; both pairs use the same native channel calls.\n\n## Related APIs\n\nIf you already know what you want to open, you can also use direct navigation helpers:\n\n- `Storyteller.openStory(..., openReason: StorytellerOpenReason.deeplink)`\n- `Storyteller.openCollection(..., openReason: StorytellerOpenReason.deeplink)`\n- `Storyteller.openCategory(..., openReason: StorytellerOpenReason.deeplink)`\n- `Storyteller.openClipByExternalId(...)` and its\n `openCollectionByExternalId(...)` alias\n\nAn explicit `StorytellerOpenReason` keeps analytics attribution consistent\nwhen your app has already classified the navigation source. If you omit it,\nthe native entry point keeps its own default.\n\nAndroid's external-ID Clips entry point always owns deep-link attribution. On\nAndroid, omit `openReason` or pass `StorytellerOpenReason.deeplink`; passing\n`StorytellerOpenReason.instanceMethod` throws an `UNSUPPORTED_ARGUMENT`\n`PlatformException`. iOS supports both reasons for the same Flutter API.\n\nSee [Storyteller API](AdditionalMethods.md) for the full list of helpers.\n\nIn the Showcase app, [`DeepLinkService._handleIncomingLink`](https://github.com/getstoryteller/storyteller-showcase-flutter/blob/main/lib/services/deep_link_service.dart#L50) validates App Links, queues them until the SDK is ready, and finally calls `Storyteller.openDeeplink`\u2014use it as a working template for production apps.\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}