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
  });
}

void stopListeningToStorytellerLinks() {
  _subscription.cancel();
}

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)
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.