Initial Setup

This guide covers the core concepts, architectural benefits, and a step-by-step implementation to help you integrate Storyly Placement into your Android 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 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, analytics, and commerce hooks 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 Flows

📘

Placement Blocks

Placement Data Provider

It fetches and manages the content/config for a placement and exposes listener callbacks.

Placement Config

It controls 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, and adapts its size to the selected widget.

Setup SDK

Import Module

Before you use Storyly Placement in your app, you must first import the Storyly Placement module.

You need to declare the dependency on module (build.gradle)

implementation("com.appsamurai.storyly:storyly-placement:<latest-version>")

📘

Tip

Please do not forget to replace <latest-version>. The latest version on Maven Central

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

🚧

Warning

Storyly SDK targets Android API level 24 (Android 7.0, Nougat) or higher.

🚧

Warning

If your application targets devices that does not contain Google APIs, you need to initialize EmojiCompat class to use Emoji related features of Storyly such as Emoji and Rating Components. Otherwise, you will encounter a crash whenever you use any of these components in your Storyly instance.

Please follow Emoji Compat Bundled Fonts initialization steps to use Emoji features of Storyly.

Initialize Components

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

STRPlacementDataProvider

You need to configure the placement data provider by creating the provider as soon as you have an ApplicationContext, set up listeners, and pass the placement token through STRPlacementConfig:

val strPlacementDataProvider = PlacementDataProvider(applicationContext).apply {
    config = STRPlacementConfig.Builder()
        .build(token = "<your_placement_token>")
}

🚧

Warning

Please login to Storyly dashboard and get your placement token.

STRPlacementView

This is the host view that actually changes widgets in and out. You attach it to your layout, initialize with PlacementDataProvider instance, and resize it whenever onWidgetReady callback is triggered.

Programmatically

Attach the placement provider to STRPlacementView programmatically

val strPlacementView = STRPlacementView(this, dataProvider = strPlacementDataProvider)
addView(strPlacementView) 

STRListener

Storyly Placement provides several listener 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 STRListener 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 PlacementView whenever the widget changes its size ratio.

The onWidgetReady callback notifies your application when the widget is ready to render with required ratio, allowing you to calculate and update the correct layout for the STRPlacementView instance.

strPlacementView.listener = object : STRListener {
    override fun onWidgetReady(widget: STRWidgetController, ratio: Float) {
        val screenWidth = Resources.getSystem().displayMetrics.widthPixels
        val targetHeight = (screenWidth / ratio).toInt()

        strPlacementView.updateLayoutParams {
            width = screenWidth
            height = targetHeight
        }
    }
}

🚧

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 'STRListener' and override 'onActionClicked' function in it. You can register the listener using the following code example:

strPlacementView.listener = object : STRListener {
    override fun onActionClicked(
        widget: STRWidgetController,
        url: String,
        payload: STRPayload
    ) {
        Log.d(logTag, "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 to correctly and check the logs to validate.

📘

Best Practices

  • You must honor onWidgetReady for responsive UI
  • You must handle onActionClickedfor navigation for action of end-user