Initial Setup

This guide covers the core concepts, architectural benefits, and a step-by-step implementation to help you integrate Storyly Placement into your Flutter 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 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 SDK in your app, you must first add the Storyly Placement package.

flutter pub add storyly_placement_flutter

Or add it manually to your pubspec.yaml:

dependencies:
  storyly_placement_flutter: <LATEST_VERSION>

📘

Tip

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

Android Installation

Flutter standard auto-linking would be sufficient for Android side.

🚧

Warning

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

iOS Installation

You need to update Pods in project's iOS side.

// this should be executed inside 'ios' folder
pod update

🚧

Warning

Storyly SDK targets iOS 12 or higher.

Initialize Components

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

StorylyPlacementProvider

You need to use StorylyPlacementProvider.create() to initialize your data source. This is an async factory method and should be called inside initState.

import 'package:storyly_placement_flutter/storyly_placement_provider.dart';

class _MyScreenState extends State<MyScreen> {
  StorylyPlacementProvider? _provider;

  @override
  void initState() {
    super.initState();
    StorylyPlacementProvider.create(
      config: StorylyPlacementConfig(
        token: '<your_placement_token_here>',
      ),
      listener: StorylyPlacementListener(
        onLoad: (event) => debugPrint('Data loaded $event'),
        onLoadFail: (event) => debugPrint('Data load failed $event'),
      ),
    ).then((provider) {
      setState(() {
        _provider = provider;
      });
    });
  }

  @override
  void dispose() {
    _provider?.dispose();
    super.dispose();
  }
}

🚧

Warning

Please login to Storyly dashboard and get your placement token.

StorylyPlacementView

This is the host widget that actually changes widgets in and out based on the placement content. You attach it to your widget tree and connect it to the provider.

import 'package:storyly_placement_flutter/storyly_placement_provider.dart';

// ... inside your build method
StorylyPlacementView(
  provider: _provider,
  onStorylyPlacementCreated: (controller) {
    _controller = controller;
  },
)

Storyly Callbacks

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

📘

Info

onWidgetReady

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

onVisibilityChange

This callback is triggered when the placement view visibility should change based on widget data availability.

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 StorylyPlacementView whenever the widget changes its size ratio.

import 'package:flutter/material.dart';
import 'package:storyly_placement_flutter/storyly_placement_provider.dart';

// ... inside your State class
double _placementHeight = 0.1; // Must be greater than 0

// ... inside your build method
SizedBox(
  height: _placementHeight,
  width: double.infinity,
  child: StorylyPlacementView(
    provider: _provider,
    onStorylyPlacementCreated: (controller) {
      _controller = controller;
    },
    onWidgetReady: (event) {
      setState(() {
        _placementHeight = MediaQuery.of(context).size.width / event.ratio;
      });
    },
  ),
)

🚧

Warning

The initial height of the SizedBox must be greater than 0. Flutter's platform view integration requires a non-zero size to trigger native rendering — a height of 0 will prevent the native view from being attached and no events will be fired.

🚧

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 the 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 the onActionClicked callback.

import 'package:flutter/material.dart';
import 'package:storyly_placement_flutter/storyly_placement_provider.dart';

PlacementWidget? _pauseWidget;

// ... inside your build method
StorylyPlacementView(
  provider: _provider,
  onStorylyPlacementCreated: (controller) {
    _controller = controller;
  },
  onActionClicked: (event) {
    _controller?.getWidget(event.widget).pause();
    _pauseWidget = event.widget;
    debugPrint('onActionClicked: url=${event.url}, payload=${event.payload}');
    // Handle navigation or custom product actions here.
    // Call _controller?.getWidget(_pauseWidget).resume() to restore once navigation is complete
  },
)

🚧

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.

Placement Visibility Handling

This section explains how to handle the visibility of the StorylyPlacementView based on whether there is a widget to display.

The onVisibilityChange callback notifies your application when the placement view's visibility should change. This happens when the widget data is successfully loaded (isVisible=true) or when there is no data or a load failure (isVisible=false).


StorylyPlacementView(
  provider: _provider,
  onStorylyPlacementCreated: (controller) {
    _controller = controller;
  },
  onVisibilityChange: (event) {
      // Update the visibility of placementView to match the state of the isVisible flag
  },
)

📘

Best Practices

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