Initial Setup

This guide covers the core concepts, architectural benefits, and a step-by-step implementation to help you integrate Storyly Placement into your iOS application.

What is Placement

Storyly Placement is a powerful, server-driven framework designed to dynamically render various widget experiences—such as Story Bars, Banners, and Swipe Cards—within a single host view. By decoupling the UI configuration from your app's codebase, Placement enables you to switch between different widget types from the Storyly Dashboard in real-time without requiring a new app release.

📘

Placement Architecture

Server Driven Surface

Placement is a server-driven surface that can render different Storyly experiences (e.g., Story Bar, Banner) in a single host view, based on configuration and rules fetched at runtime.

Single Integration Point

It centralizes data loading, rendering, and analytics via a single provider and a single view, enabling sophisticated, dynamic experiences without hardcoding which widget to show.

Core Building Blocks

These core building blocks are mandatory to integrate and start enabling features with Storyly on iOS.

📘

Placement Blocks

Placement Data Provider

It fetches and manages the content/config for a placement and exposes delegate callbacks via STRProviderDelegate.

Placement Config

The block where the placement token is injected, it also controls configurations like test mode, user/targeting context, and layout direction.

Placement View

It hosts the actual widget determined at runtime (e.g., Story Bar, Banner), exposes UI and analytics callbacks through STRDelegate, and adapts its size to the selected widget.

Setup SDK

Before using Storyly Placement in your iOS app, make sure the Storyly Placement SDK is added to your project (via Swift Package Manager or CocoaPods), then import the module in the files where you initialize Placement

🚧

Warning

Storyly SDK targets iOS 12 or higher.

📘

Tip

You can find the latest version’s release notes here.

CocoaPods

Add the corresponding StorylyPlacement pod to your Podfile, run pod install, and open the generated workspace.

use_frameworks!
pod 'StorylyPlacement'

Swift Package Manager

Storyly SDK is available through SPM. To integrate Storyly SDK into your Xcode project using SPM, add and enter package repository in the Swift Packages tab of your project.

Import Module

You need to import related modules to use Storyly:

import StorylyPlacement
import StorylyCore

Initialize Components

This section explains how to set up and connect the core Placement components: data provider, placement view, and delegate callbacks.

STRPlacementDataProvider

You should initialize the placement data provider early in your application flow, and supply the placement token via STRPlacementConfig. The provider’s responsibility is limited to fetching, managing, and exposing placement data; it operates independently of any UI layer and serves purely as a data engine.

private lazy var placementProvider: PlacementDataProvider = {
    let provider = PlacementDataProvider()
    return provider
}()

STRPlacementConfig

You configure a placement by supplying a STRPlacementConfig, which specifies the placement token and defines how the data provider should operate. The config does not load or render anything on its own; instead, it provides the essential metadata the data provider needs to retrieve and manage placement content.

private func setupPlacementConfig() {
    placementProvider.config = STRPlacementConfig.Builder()
        .build(token: "<your_placement_token_here>")
}

🚧

Warning

Please login to Storyly dashboard and get your placement token.

STRPlacementView

This is the host view that actually changes widgets in and out based on the placement content. You attach it to your hierarchy and connect it to the PlacementDataProvider. Its responsibility is limited to presentation and user interaction, relying on a rootViewController only when UI presentation is required.

private func setupPlacementView() {
    placementView = STRPlacementView(dataProvider: placementProvider)
    placementView.rootViewController = self
}

STRDelegate

Storyly Placement provides several delegate callbacks that allow your application to react to changes in widget state, user interactions, and analytics events.

To observe and respond to these behaviors, you must assign an STRDelegate to the STRPlacementView.

📘

Info

onWidgetReady

This callback is triggered when the active widget ready to render. It gives a width-to-height ratio for the best rendering of view.

onActionClicked

This callback is triggered when the user interacts with the widget’s action area (e.g., swipe-up or action button).

Placement Size Handling

This section explains how to resize the STRPlacementView whenever the widget reports a new aspect ratio.

The onWidgetReady callback notifies your application when the widget is ready to render with the required ratio. At that point, you can calculate the target height using the current view width and update the height constraint of the placement view.

extension ViewController: STRDelegate {
    func onWidgetReady(widget: STRWidgetController, ratio: CGFloat) {

        // Calculate target height using the reported ratio
        let width = view.bounds.width
        guard width > 0 else { return }

        let targetHeight = width / ratio
        placementHeightConstraint?.constant = targetHeight

        UIView.animate(withDuration: 0.25) {
            self.view.layoutIfNeeded()
        }
    }
}

🚧

Warning

You must test with different widget types in the Dashboard's Placement page to verify that dynamic sizing behaves as expected. You can use this as a verification step in your initialization.

Placement Action Handling

This section shows how to handle Swipe Up and Action Button clicks from user.

The redirection needs to be handled by the application itself when the end‑user clicks any action in the content. In order to handle this action, you must register STRDelegate and override onActionClicked function in it.

extension ViewController: STRDelegate {
  func onActionClicked(widget: STRWidgetController, url: String, payload: STRPayload) {
    print("onActionClicked: url=\(url), payload=\(payload)")
    // In a real app, navigate using the URL or handle product actions here.
  }
}

🚧

Warning

Please confirm onActionClicked callback is triggered upon any action in the content. Make sure your app navigates correctly and check the logs to validate.

📘

Best Practices

  • You must honor onWidgetReady for responsive UI.
  • You must handle onActionClicked for navigation for actions of end‑user.