App In-line Content

Deliver personalized in-app messages to your Flutter users. Leverage Antsomi SDK for targeted communication & a frictionless user experience.

Supported from Antsomi SDK v0.0.29.

App In-line Content allows you to insert content directly into your app's screen without disturbing the user experience. It also allows you to dynamically update your app's content and run relevant and contextual campaigns.

You may use the In-line Content to change areas of your app or show banner ads based on live triggers and segmentation.

This capability is provided in the Antsomi Media JSON feature. If you are not familiar with this feature, head over to this document.

What is Media JSON?

Media JSON acts as a structured data format that stores content and configuration information associated with Customer Journeys within CDP365. These Customer Journeys represent pre-defined sequences of interactions or touchpoints designed to engage users based on their behavior and attributes. By associating Media JSON with specific Customer Journeys, you can dynamically deliver personalized content to users at the right time.

Implementation with Antsomi Flutter SDK

The Antsomi Flutter SDK offers functionalities to retrieve Media JSON for your Flutter applications. Here's a breakdown of the process:

Before continuing, please ensure that you've added the Flutter SDK to your app.

1. Retrieving Media JSON data

Once you have access to the initialized AntsomiSDK instance (assuming you've completed the initialization steps as documented by the Antsomi SDK provider), you can utilize the getMediaJson() method in the screen that you want to display the App In-Line Content by following:

import 'package:antsomisdk/antsomi.dart'; // Contains Antsomi SDK APIs
import 'package:antsomisdk/cdp_event.dart'; // Contains Antsomi SDK APIs
import 'package:antsomisdk/media_json.dart'; // Contains the Catalog class

final event = CDPEvent(en: 'view_screenview');
event.eventProps = {'screen_name': 'templateMediaJson'};

const storyId = '123';

// Initialize AntsomiSDK object
antsomiSdk = Antsomi();
final MediaJson mediaJson = await antsomiSdk.getMediaJson(event: event, storyId: storyId);

This method takes two arguments:

FieldData TypeDescription

event

CDPEvent

The specific event name corresponds to the event configured within your CDP365 workspace to initiate the relevant Customer Journey.

storyId

String

(Optional) Allows you to specify a particular journey within the Customer Journey triggered by the event. If omitted, the Media JSON for the default journey associated with the event will be retrieved.

The retrieved MediaJson is a structured data format containing various properties relevant to personalization. While the exact structure might vary depending on your CDP365 configuration, here's a general overview of the common elements:

FieldData TypeDescription

status

bool

The status of getting the Media JSON, always check this key first to prevent errors.

webContents

Map<string, dynamic>?

This key contains the main content data.

contents

Map<string, dynamic>

This nested map holds the actual content associated with the Customer Journey.

globalTracking

Map<string, dynamic>

This map might contain global tracking information like impression and view URLs or UTM modules used for tracking purposes within CDP365.

view

String

The global view URL tracking information.

impression

String

The global impression URL tracking information.

atmTrackingParameters

String

The global UTM/ATM modules string.

2. Utilizing Retrieved Media JSON

Once you have successfully retrieved the Media JSON object, you can leverage the data to personalize user experiences within your Flutter applications. Here are some potential use cases:

Populate UI Elements

For example, take a look at a Media JSON configured as below:

With this setup, we can extract dynamic content from the dynamicContent object and use it to populate UI elements like images, product names, prices, or descriptions to recommend our end-users with the latest trending products as the following:

@override
Widget build(BuildContext context) {
    return Scaffold(
    // ... More code here
    child: Container(
        height: 200, // Adjust the height as needed
        color: Colors.white,
        child: SingleChildScrollView(
            controller: _scrollController,
            scrollDirection: Axis.horizontal,
            child: Row(
                children: dynamicContent.map((content) {
                  return GestureDetector(
                    onTap: () {
                      // onTap() handlers...                      
                  },
                  child: SizedBox(
                    width: 150, // Adjust the width as needed
                    child: Column(
                      children: [
                        Image.network(
                          content['image_url'],
                          height: 150,
                        ), // Image.network
                        Text(content['name']),
                        Text(content['price']),
                      ],
                    ), // Column
                  ), // SizedBox
                ); // GestureDetector
              }).toList(),
            ), // Row

    // ... More code here

And you will receive something similar to this

3. Trigger Tracking Events

Utilize tracking URLs found within the globalTracking map (if applicable) to trigger events within CDP365 based on user interactions with personalized content such as impression, viewable, item clicked, or UTM tracking.

For instance, let's say we are building a section that shows a list of personalized recommended products for our end-users, these products are precisely selected via our algorithms and delivered to each end-user through the Customer Journeys.

Impression Event

When the screen is loaded and you have successfully requested the list of the recommended products. This is the impression event that should be fired as soon as the request is successfully made. After invoking the getMediaJson() and getting the list of recommended products, please invoke this function:

if (mediaJson.webContents?['contents']?['globalTracking']?['impression'] != null) {
    antsomiSdk.handleTrackingUrl(url: Uri.parse(mediaJson.webContents!['contents']!['globalTracking']!['impression']));
}

Viewable Event

When a user scrolls down the screen the specific recommended products section is displayed. This is the viewable event. This event should be fired once the section is partially visible. After making the API request and getting the list of recommended products, and the displayed section is partially visible, invoke the function like the example below:

// Check visibility when the screen is loaded
WidgetsBinding.instance.addPostFrameCallback((_) {
  if (_isRowVisible()) {
    // Check if the second row is visible when the screen is loaded
    if (mediaJson.webContents?['contents']?['globalTracking']?['view'] != null) {
      antsomiSdk.handleTrackingUrl(url: Uri.parse(mediaJson.webContents!['contents']!['globalTracking']!['view']));
    }
  }
});

Click Item Event

When the list of recommended products is loaded, and our user taps on any one of them. This is the click item event. This event should be fired once the section is partially visible. After making the API request and getting the list of recommended products, and the displayed section is partially visible, invoke the function like the example below:

@override
Widget build(BuildContext context) {
    return Scaffold(
    // ... More code here
    child: Container(
        height: 200, // Adjust the height as needed
        color: Colors.white,
        child: SingleChildScrollView(
            controller: _scrollController,
            scrollDirection: Axis.horizontal,
            child: Row(
                children: dynamicContent.map((content) {
                  return GestureDetector(
                    onTap: () {
                        if (content['page_url_with_tracking_click'] != null) {                            
                            var trackingLink = Uri.parse(content['page_url_with_tracking_click']);
                            AntsomiSDK.instance.handleTrackingUrl(url: trackingLink);
                            
                            // Redirect your end-user to the Product Screen here...
                        }
                  },
                  child: SizedBox(
                    // ... More code here
                ); // GestureDetector
              }).toList(),
            ), // Row

    // ... More code here

ATM/UTM Tracking

And finally, what if you want to set some UTM/ATM tracking modules so that you can unify the source of events, just simply include the value of the atmTrackingParameters in the globalTracking map and invoke the handleDeepLink() method. From now on, every event that our SDK tracked will be automatically included with this UTM/ATM tracking module.

@override
Widget build(BuildContext context) {
    return Scaffold(
    // ... More code here
    child: Container(
        height: 200, // Adjust the height as needed
        color: Colors.white,
        child: SingleChildScrollView(
            controller: _scrollController,
            scrollDirection: Axis.horizontal,
            child: Row(
                children: dynamicContent.map((content) {
                  return GestureDetector(
                    onTap: () {
                        if (content['page_url_with_tracking_click'] != null) {
                            var deepLink = Uri.parse(content['page_url'] + '?' + globalTracking?['atmTrackingParameters']);
                            var trackingLink = Uri.parse(content['page_url_with_tracking_click']);
                            
                            antsomiSdk.handleDeepLink(url: deepLink);
                            antsomiSdk.handleTrackingUrl(url: trackingLink);
                            
                            // Redirect your end-user to the Product Screen here...
                        }
                  },
                  child: SizedBox(
                    // ... More code here
                ); // GestureDetector
              }).toList(),
            ), // Row

    // ... More code here

By effectively utilizing App In-line Content and the Antsomi Flutter SDK, you can create a more dynamic and engaging user experience within your Flutter applications. This capability allows you to deliver personalized content, trigger relevant campaigns, and gain valuable insights into user interactions. Remember to refer to the specific documentation provided by your chosen App In-line Content solution for detailed integration steps and functionalities.

Last updated