Skip to content

Deep Linking#

Deep linking has two sides:

  1. Opening Storyteller content from an incoming URL (e.g. a user taps a Storyteller link and your app launches)
  2. Navigating back to your app from Storyteller UI (e.g. a Story page action button uses your app's URL scheme)

This page focuses on the Flutter SDK API surface. You still need the usual platform setup for app links/universal links on Android and iOS.

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';

late final StreamSubscription<String> _subscription;

void startListeningToStorytellerLinks() {
  _subscription = Storyteller.userNavigatedToApp.listen((url) {
    // Parse and route using your app's navigation system.
    // Example: myapp://product/123
  });
}

Future<void> stopListeningToStorytellerLinks() async {
  await _subscription.cancel();
}

Queue incoming URLs until Storyteller.initialize(...) returns success: true; then process each queued URL once. The SDK does not install your Android intent filters or iOS associated domains.

If your app receives a URL (from your existing deep-link handling setup), you can forward Storyteller links to the SDK:

  1. Check the URL with Storyteller.isStorytellerDeepLink(url)
  2. If true, call Storyteller.openDeepLink(url) and handle errors. Detection recognizes Storyteller URLs; it does not confirm that the content exists or can be opened.
import 'package:storyteller_sdk/storyteller_sdk.dart';

Future<void> handleIncomingUrl(String url) async {
  if (await Storyteller.isStorytellerDeepLink(url)) {
    await Storyteller.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.

If you already know what you want to open, you can also use direct navigation helpers:

  • Storyteller.openStory(..., openReason: StorytellerOpenReason.deeplink)
  • Storyteller.openCollection(..., openReason: StorytellerOpenReason.deeplink)
  • Storyteller.openCategory(..., openReason: StorytellerOpenReason.deeplink)
  • 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_ARGUMENT PlatformException. iOS supports both reasons for the same Flutter API.

See Storyteller API for the full list of helpers.

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.

If a recognized URL opens no content, verify initialization, the URL's content identifiers and publication state, and the platform link configuration. See Troubleshooting.