Search and its Storyteller.shared.openSearch() and isSearchEnabled APIs are available only on iOS.
The Search component allows users to search for Storyteller Stories and Clips, plus external Articles when an Article source is configured for the tenant. As users type, a list of suggestions appears, from which users can either select a suggestion or search using their entered term. Result sections retain the order configured for the tenant. Filters allow users to narrow down their search results by date or content type and change their sort order.
Stories, Clips, and external Articles share the same section configuration through remote Settings in the CMS using theme.behavior.search.visibleLists. This controls which sections appear, their order, titles, and item limits. No additional configuration is required in your app.
Story and Clip sections support row or grid layouts. Articles appear in a horizontal carousel with up to 20 results per query and no additional paging.
When no section configuration is supplied, Search displays a Stories row followed by a Clips grid. A configured list replaces those defaults, including an empty list hiding all sections. Invalid entries are ignored independently, and Search content-type filters apply to the configured sections.
Each Article card displays its title and optional display date. Tapping a card executes the Action supplied with that result through the same Storyteller Action handling used by other SDK surfaces. A malformed Article is omitted independently. An empty or failed Article source removes only that section, so configured Story and Clip results remain available.
Article visibility and taps are available through StorytellerDelegate.onUserActivityOccurred(type:data:). See External Search Result Events for the event and payload contract.
Clips opened from Search show eligible categories supplied with each Clip. A category needs a nonblank external ID and display title and must be available for navigation; omitted availability defaults to enabled. Category type, Follow availability, and visibility in collection feeds do not control this Search navigation.
Tapping a category opens its Latest Clips across the tenant, starting with the first returned Clip. Search terms, sorting and date filters do not restrict the category feed. Further category taps use the categories attached to the displayed Clip.
Back returns one level at a time, retaining the previous Clip and its playback position and play/pause state. Closing a Clip Player opened from Search restores the Search query, filters and results. Search Clip lists retain their loaded results on close even when the remote theme.behavior.reloading.reloadOnExit setting is enabled, including journeys where no category was opened. Empty categories keep Back available; failed loads offer Retry, and failed later pages retain the Clips already loaded.
The Search feature must first be enabled by the Storyteller team for your specific tenant. Once enabled, the Search functionality will be available within the Story and Clip players.
Additional Search functionality is available through the Storyteller class:
isSearchEnabled - synchronously returns the cached Search setting. It is authoritative for the current tenant after successful SDK initialization.
openSearch - opens the Search component from anywhere in the app when enabled. If a Storyteller Player is currently displayed, it is dismissed before Search is presented.
Important:openSearch() waits for successful SDK initialization before presenting Search. If SDK initialization never succeeds, the call remains suspended and no UI is presented. Ensure Storyteller.shared.initialize(...) is called during normal app startup.
openSearch() is asynchronous and non-throwing. When Search is disabled, it returns without presenting anything or dismissing the current Player. Before initialization succeeds, isSearchEnabled may reflect default or cached settings and is authoritative for the current tenant only when isInitialized is true:
importStorytellerSDKfuncsearchButtonTapped(){Task{@MainActorin// The SDK is expected to be initialized before checking this property.guardStoryteller.shared.isSearchEnabledelse{print("Storyteller Search is not enabled for this tenant")return}awaitStoryteller.shared.openSearch()}}
The Showcase app triggers openSearch from the home header button - see HomeView.headerView.
The Search background, input, filter button, suggestions, no-results state and filter sheet can be customized independently for light and dark themes. All appearance properties are optional and retain the existing UI when omitted. For the full property contract and inheritance rules, see Search themes.
{"slug": "search", "page_title": "Add Content Search", "page_url": "Search/", "canonical_url": "/ios/Search/", "markdown": "# Search\n\nSearch and its `Storyteller.shared.openSearch()` and `isSearchEnabled` APIs are available only on iOS.\n\nThe `Search` component allows users to search for Storyteller Stories and Clips, plus external Articles when an Article source is configured for the tenant. As users type, a list of suggestions appears, from which users can either select a suggestion or search using their entered term. Result sections retain the order configured for the tenant. Filters allow users to narrow down their search results by date or content type and change their sort order.\n\n[](){ #article-results }\n\n## Search Result Sections\n\nStories, Clips, and external Articles share the same section configuration through remote Settings in the CMS using `theme.behavior.search.visibleLists`. This controls which sections appear, their order, titles, and item limits. No additional configuration is required in your app.\n\nStory and Clip sections support row or grid layouts. Articles appear in a horizontal carousel with up to 20 results per query and no additional paging.\n\nWhen no section configuration is supplied, Search displays a Stories row followed by a Clips grid. A configured list replaces those defaults, including an empty list hiding all sections. Invalid entries are ignored independently, and Search content-type filters apply to the configured sections.\n\nEach Article card displays its title and optional display date. Tapping a card executes the Action supplied with that result through the same Storyteller Action handling used by other SDK surfaces. A malformed Article is omitted independently. An empty or failed Article source removes only that section, so configured Story and Clip results remain available.\n\nArticle visibility and taps are available through `StorytellerDelegate.onUserActivityOccurred(type:data:)`. See [External Search Result Events](Analytics.md#external-search-result-events) for the event and payload contract.\n\n## Clip Category Navigation\n\nClips opened from Search show eligible categories supplied with each Clip. A category needs a nonblank external ID and display title and must be available for navigation; omitted availability defaults to enabled. Category type, Follow availability, and visibility in collection feeds do not control this Search navigation.\n\nTapping a category opens its Latest Clips across the tenant, starting with the first returned Clip. Search terms, sorting and date filters do not restrict the category feed. Further category taps use the categories attached to the displayed Clip.\n\nBack returns one level at a time, retaining the previous Clip and its playback position and play/pause state. Closing a Clip Player opened from Search restores the Search query, filters and results. Search Clip lists retain their loaded results on close even when the remote `theme.behavior.reloading.reloadOnExit` setting is enabled, including journeys where no category was opened. Empty categories keep Back available; failed loads offer Retry, and failed later pages retain the Clips already loaded.\n\n## Search Filters\n\n`Date Posted` possible values:\n\n- `All` - default value\n- `Past 24 hours`\n- `Last Week`\n- `Last Month`\n- `Last Year`\n\n`Content Type` possible values:\n\n- `All` - default value\n- `Stories`\n- `Clips`\n- `Articles` - shown only when a valid Article source is configured\n\n`Sort By` values:\n\n- `Relevance` - default value\n- `Like Count`\n- `Share Count`\n- `Date Posted`\n\n## How to Use\n\nThe `Search` feature must first be enabled by the Storyteller team for your specific tenant. Once enabled, the Search functionality will be available within the Story and Clip players.\n\nAdditional `Search` functionality is available through the `Storyteller` class:\n\n- `isSearchEnabled` - synchronously returns the cached Search setting. It is authoritative for the current tenant after successful SDK initialization.\n- `openSearch` - opens the `Search` component from anywhere in the app when enabled. If a Storyteller Player is currently displayed, it is dismissed before Search is presented.\n\n**Important:** `openSearch()` waits for successful SDK initialization before presenting Search. If SDK initialization never succeeds, the call remains suspended and no UI is presented. Ensure `Storyteller.shared.initialize(...)` is called during normal app startup.\n\n`openSearch()` is asynchronous and non-throwing. When Search is disabled, it returns without presenting anything or dismissing the current Player. Before initialization succeeds, `isSearchEnabled` may reflect default or cached settings and is authoritative for the current tenant only when `isInitialized` is `true`:\n\n<!-- storyteller-swift-example: id=search-open target=sdk-ios context=declarations -->\n\n```swift\nimport StorytellerSDK\n\nfunc searchButtonTapped() {\n Task { @MainActor in\n // The SDK is expected to be initialized before checking this property.\n guard Storyteller.shared.isSearchEnabled else {\n print(\"Storyteller Search is not enabled for this tenant\")\n return\n }\n\n await Storyteller.shared.openSearch()\n }\n}\n```\n\nThe Showcase app triggers `openSearch` from the home header button - see [`HomeView.headerView`](https://github.com/getstoryteller/storyteller-showcase-ios/blob/11.8.0/main/ShowcaseApp/Views/Home/HomeView.swift#L252).\n\n## Customization\n\nThe Search background, input, filter button, suggestions, no-results state and filter sheet can be customized independently for light and dark themes. All appearance properties are optional and retain the existing UI when omitted. For the full property contract and inheritance rules, see [Search themes](Themes.md#search).\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}