Initial SDK Setup

Initial SDK Setup

This walkthrough shows how to add Storyly to your Android application and show your first Story in it.

👍

You can also check out the demo on GitHub

Storyly Demo for Kotlin

Storyly Demo for Java

📘

Before you begin

This walkthrough contains sample instance information. However, if you want to work with your own content as well, please login into Storyly Dashboard and get your instance token.

The sample instance information for testing purposes;

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NfaWQiOjc2MCwiYXBwX2lkIjo0MDUsImluc19pZCI6NDA0fQ.1AkqOy_lsiownTBNhVOUKc91uc9fDcAxfQZtpm3nj40

Installation

First, declare the dependency for the Storyly SDK in your app’s module Gradle file (usually app/build.gradle).

android {
    dependencies {
        ...
        // You should add this line
        implementation 'com.appsamurai.storyly:storyly:<latest-version>'
        ...
    }
}

📘

Tip

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

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

🚧

Warning

Storyly SDK targets Android API level 17 (Android 4.2, Jelly Bean) 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.

Add Storyly View

You can add StorylyView to your app either from XML layout or using the programmatic approach.

StorylyView extends ViewGroup so that you can use inherited functionality as it is. So, you can add StorylyView to any of the app’s layouts as a View component.

Adding from XML Layout

Open your XML layout and add these lines wherever you want to add StorylyView

<com.appsamurai.storyly.StorylyView
    android:id="@+id/storyly_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Programmatically

StorylyView extends ViewGroup so that you can use inherited functionality as it is. So, you can initialize StorylyView using View’s constructors.

val storylyView = StorylyView(this)
addView(storylyView)
StorylyView storylyView = new StorylyView(this);
addView(storylyView);

Initialize StorylyView

You are one step away from enjoying Storyly. You just need to initialize StorylyView.

storylyView.storylyInit = StorylyInit(STORYLY_INSTANCE_TOKEN)
storylyView.setStorylyInit(new StorylyInit(STORYLY_INSTANCE_TOKEN));

📘

Tip

Please do not forget to use your own token. You can get your token from the Storyly Dashboard -> Settings -> App Settings

Just hit the run. Now, you should be able to enjoy Storyly :tada:!

1549

🚧

Warning

While initializing the StorylyView, extra settings should be done with Config parameter. The aim is to gather all of the listed methods under the Config parameter.

You can check the usage of config parameter as shown below and can check Configuration section for more details.

While initializing the StorylyView, extra settings should be done with Config parameter. The aim is to gather all of the listed methods under the Config parameter.

Configuration

Config parameter includes all of the features and functionalities listed below:

All the methods listed above should be set under Config parameter.

🚧

Warning

Please check the relevant section for a detailed explanation.

storylyView.storylyInit = StorylyInit(
            storylyId: storylyToken,
            config: StorylyConfig.Builder()
               .setBarStyling(
                    styling: StorylyBarStyling.Builder()
                        .setHorizontalPaddingBetweenItems(padding: 15)
                        .build()
               )
               .setStoryGroupStyling(
                   styling: StorylyStoryGroupStyling.Builder()
                       .setSize(size: .Custom)
                       .setIconHeight(height: 110)
                       .setIconWidth(width: 160)
                       .setIconCornerRadius(radius: 12)
                       .build()
                )
                .setStoryStyling(
                    styling: StorylyStoryStyling.Builder()
                        .setInteractiveFont(Typeface.MONOSPACE)
                        .build()
                )
                .setUserData(data: Map<String, String>)
                .setLabels(labels: Set<String>?)
                .setCustomParameter(parameter: String?)
                .setLayoutDirection(StorylyLayoutDirection.LTR | .RTL)
                .setTestMode(true)
                .setLocale(locale: String?)
                .setProductConfig(
                    config: StorylyProductConfig.Builder()
                        .setFallbackAvailability(true)
                        .build()
                )
                .setStorylyPayload(payload: String?)
                .setShareConfig(
                    StorylyShareConfig.Builder()
                        .setShareUrl(url: String)
                        .setFacebookAppID(id: String)
                        .build()
                )
                .build()
        )

Set Up Listener

This walkthrough shows you how to handle Storyly events in your app. Storyly events provide insight into what is happening on a Storyly instance such as loading states.

📘

Before you begin

You need to have the working Storyly integration as described in Initial SDK Setup

StorylyView notifies the application when an event occurs. You can register the listener using the following code example and then override its functions to learn about specific events, which will be explained in the next sections.

storylyView.storylyListener = object : StorylyListener {
    // Override event functions
}
storyly_view.setStorylyListener(new StorylyListener() {
    // Override event methods
});

In order to get notification about these basic events, you should override the following functions in StorylyListener.

StorylyLoaded Event

This event will let you know that Storyly has completed its network operations, and the Story Group list has just been shown to the user. In order to be notified about this event, use the following example:

override fun storylyLoaded(storylyView: StorylyView, 
                           storyGroupList: List<StoryGroup>,
                           dataSource: StorylyDataSource) {}
@Override
public void storylyLoaded(@NonNull StorylyView storylyView, 
                          @NonNull List<StoryGroup> storyGroupList,
                          @NonNull StorylyDataSource dataSource) {}

StorylyLoadFailed Event

This event will let you know that Storyly has completed its network operations and had a problem while fetching your Stories. In this case, users will see four empty Story Group icons, which we call skeleton view. In order to be notified about this event, use the following example:

override fun storylyLoadFailed(storylyView: StorylyView, 
                               errorMessage: String) {}
@Override
public void storylyLoadFailed(@NonNull StorylyView storylyView, 
                              @NonNull String errorMessage) {}

How to Show/Hide Storyly Bar

This guide shows use cases for showing or hiding the Storyly bar in your app. To increase user experience when there are no Stories available or Stories are not loading using Storyly event handling.

👍

You can also check out the demo on GitHub

Storyly Demo for Kotlin

Storyly Demo for Java

📘

Before you begin

You need to have the working Storyly setup as described in Initial SDK Setup

Show Storyly

Use case for showing Storyly if StorylyView is loaded and Stories are available.

Create layout xml with added StorylyView. Initialize StorylyView with the token from the dashboard.

Not to show the already visible StorylyView bar, check if initially loaded and storyGroupList size. Set StorylyView visibility to View.VISIBLE.

📘

Event handling

storylyLoaded event triggers first for available cached stories and second for request response with current stories.
Detailed information about Set Up Listener

binding.storylyView.storylyListener = object : StorylyListener {
    var initialLoad = true

    override fun storylyLoaded(storylyView: StorylyView, storyGroupList: List<StoryGroup>) {
        //  for not to re-animate already loaded StorylyView
        if (initialLoad && storyGroupList.isNotEmpty()) {
            initialLoad = false
            storylyView.visibility = View.VISIBLE
        }
    }
    // ... other storyly events
}
storylyView.setStorylyListener(new StorylyListener() {
    boolean initialLoad = true;

    @Override
    public void storylyLoaded(@NotNull StorylyView storylyView, @NotNull List<StoryGroup> storyGroupList) {
        //  for not to re-animate already loaded StorylyView
        if (initialLoad && storyGroupList.size() > 0) {
            initialLoad = false;
            storylyView.setVisibility(View.VISIBLE);
        }
    }
    // ... other storyly events
}

Hide Storyly

Use case for hiding Storyly if StorylyView is not loaded and Stories are not available.

Create layout xml with added StorylyView. Initialize StorylyView with the token from the dashboard.

Not to show already visible StorylyView bar, check if initially loaded and storyGroupList size. Set StorylyView visibility to View.VISIBLE.

Loading cached stories triggers storylyLoaded event before storylyLoadFailed event. Check for if the cache is loaded and storyGroupList size. If the cache or request is not loaded, set the StorylyView visibility to View.INVISIBLE or Visibility.GONE.

📘

Event handling

storylyLoaded event triggers first for available cached stories and later for up to date stories.
storylyLoaded for cached stories will trigger before storylyLoadFailed.

binding.storylyView.storylyListener = object : StorylyListener {
    var storylyLoaded = false

    override fun storylyLoaded(storylyView: StorylyView, storyGroupList: List<StoryGroup>) {
        if (storyGroupList.isNotEmpty()) {
            storylyLoaded = true
        }
    }

    override fun storylyLoadFailed(storylyView: StorylyView, errorMessage: String) {
        // if cached before not hide
        if (!storylyLoaded) {
            storylyView.visibility = View.GONE;
        }
    }
    //  ... other used Storyly events
}
storylyView.setStorylyListener(new StorylyListener() {
    boolean storylyLoaded = false;

    @Override
    public void storylyLoaded(@NotNull StorylyView storylyView, @NotNull List<StoryGroup> list) {
        if (list.size() > 0) {
            storylyLoaded = true;
        }
    }

    @Override
    public void storylyLoadFailed(@NotNull StorylyView storylyView, @NotNull String errorMessage) {
        // if cached before not hide
        if (!storylyLoaded) {
            storylyView.setVisibility(View.GONE);
        }
    }
    //  ... other used Storyly events
});

Set Up Product Listener

This walkthrough shows you how to handle Shoppable Stories events in your app. Shoppable Stories' events provide insight into what is happening on Storyly instance related to products.

📘

Before you begin

You need to have the working Storyly integration as described in Initial SDK Setup

StorylyView notifies the application when an event occurs. You can register the listener using the following code example and then override its functions to learn about specific events, which will be explained in the next sections.

storylyView.storylyProductListener = object : StorylyProductListener {
    // Override event functions
}
storyly_view.setStorylyProductListener(new StorylyProductListener() {
    // Override event methods
});

In order to get notification about these basic events, you should override the following functions in StorylyProductListener.

storylyUpdateCartEvent

This function will notify you about updates to the cart in a StorylyView component.

STRCartItem

This class represents an individual item in the shopping cart. You can find the all properties of STRCartItem here.

📘

Info

You can get the productId, productGroupId, price, salesPrice, currency, desc etc under change.item.

onSuccess

It represents a callback function that will be executed if the "update cart" operation is successful.

onSuccess?.invoke(STRCart(items = listof(),
                          oldTotalPrice = Float, 
                          totalPrice = Float,
                          currency = String?
                         ))

onFail

It represents a callback function that will be executed if the "update cart" operation fails.

onFail?.invoke(STRCartEventResult("Your Failed Message"))

Usage of storylyUpdateCartEvent

storylyView.storylyProductListener = object : StorylyProductListener {
    /**
     * This function will notify you about updates the cart in a StorylyView component
     *
     * storylyView: StorylyView instance in which the event is received
     * event: Storyly event type which is received
     * cart: Contains information about the items in the cart
     * change: Represents the item being changed in the cart.
     * onSuccess: It represents a callback function that will be executed if the "update cart" operation is successful
     * onFail: It represents a callback function that will be executed if the "update cart" operation fails
     *
     */
   override fun storylyUpdateCartEvent(
                storylyView: StorylyView,
                event: StorylyEvent,
                cart: STRCart?,
                change: STRCartItem?,
                onSuccess: ((STRCart?) -> Unit)?,
                onFail: ((STRCartEventResult) -> Unit)?,
            ) {
                when (event){
                    StorylyEvent.StoryProductAdded -> {
                        Log.d("Shopping", "StoryProductAdded")
                        //This event sent when a product is added.
                    }
                    StorylyEvent.StoryProductUpdated -> {
                        Log.d("Shopping", "StoryProductUpdated")
                        //This event sent when a product is updated.
                    }
                    StorylyEvent.StoryProductRemoved -> {
                        Log.d("Shopping", "StoryProductRemoved")
                        //This event sent when a product is removed.
                    }
                }

                Log.d("Shoppable", "ShoppableEvent: ${event}")
                Log.d("Shoppable", "ShoppableCart: ${cart}")
                Log.d("Shoppable", "ShoppableChange: ${change}")
                
                 onSuccess?.invoke(STRCart(items = listof(),
                                           oldTotalPrice = Float, 
                                           totalPrice = Float,
                                           currency = String?
                                          ))
                 onFail?.invoke(STRCartEventResult("Your Failed Message"))
            }
        }
}

storylyEvent

This function will notify you about all Storyly events so that you can make redirections accordingly. Also, you can send these events to your data platform to track user journeys on your end.

Usage of storlyEvent

storylyView.storylyProductListener = object : StorylyProductListener {
    override fun storylyEvent(storylyView: StorylyView, event: StorylyEvent) {
                when (event){
                    StorylyEvent.StoryCheckoutButtonClicked -> {
                        Log.d("Shopping", "StoryCheckoutButtonClicked")
                    }
                    StorylyEvent.StoryCartButtonClicked -> {
                        Log.d("Shopping", "StoryCartButtonClicked")
                    }
                    StorylyEvent.StoryCartViewClicked -> {
                        Log.d("Shopping", "StoryCartViewClicked")
                    }
                    StorylyEvent.StoryProductSelected -> {
                        Log.d("Shopping", "StoryProductSelected")
                    }
                }
            }
}
storyly_view.setStorylyProductListener(new StorylyProductListener() {
    override fun storylyEvent(
      @NonNull storylyView: StorylyView, 
      @NonNull event: StorylyEvent) {
                when (event){
                    StorylyEvent.StoryCheckoutButtonClicked -> {
                        Log.d("Shopping", "StoryCheckoutButtonClicked")
                     
                    }
                    StorylyEvent.StoryCartButtonClicked -> {
                        Log.d("Shopping", "StoryCartButtonClicked")
                    }
                    StorylyEvent.StoryCartViewClicked -> {
                        Log.d("Shopping", "StoryCartViewClicked")
                    }
                    StorylyEvent.StoryProductSelected -> {
                        Log.d("Shopping", "StoryProductSelected")
                    }
                }
            }
});

StoryCheckoutButtonClicked Event

If isProductCartEnabled is set to true, this event is sent when the "Go to Checkout" button is clicked.

StoryCartButtonClicked Event

This event is sent when the "Go to Cart" button is clicked from the success sheet.

StoryCartViewClicked Event

This event is sent when the cart icon on Story is clicked.

StoryProductSelected Event

This event is sent when the product is selected.

storylyHydration

This function will notify you to get the products placed in Stories.

storylyView.storylyProductListener = object : StorylyProductListener {
    override fun storylyEvent(
                storylyView: StorylyView,
                event: StorylyEvent,
                product: STRProductItem?,
                extras: Map<String, String>
            ) {
 					/**
					* This function will notify you to get the products placed in Stories.
				 	*	
 					* - Parameter storylyView: StorylyView instance in which the user interacted with a component
 					* - Parameter productIds: Data class that represents the storyly product information
 					*/
					override fun storylyHydration(storylyView: StorylyView, products: List<STRProductInformation>) {
                Log.d("Shopping", "storylyHydration: ${products.toList()}")
            }
          }
}

Example of Product Listener

You can find the usage of Product Listener in our Recipe which is below.

Test Mode

📘

Before you begin

You need to have the working Storyly integration as described in Initial SDK Setup

This guide shows how to show test groups created in Storyly Dashboard to the specific devices. The default value of isTestMode is false, you need to explicitly define to set test devices.

storylyView.storylyInit = StorylyInit(STORYLY_INSTANCE_TOKEN, isTestMode = true)
storylyView.setStorylyInit(new StorylyInit(STORYLY_INSTANCE_TOKEN, true));

Localization

This guide will walk you through the process of localizing all Storyly-related texts and content. You can deliver the appropriate content to each language/country pair by passing the locale parameter on the client side.

To set the locale, you need to use the IETF BCP 47 format as shown below:

storylyView.storylyInit = StorylyInit(
            storylyId: storylyToken,
            config: StorylyConfig.Builder()
               .setLocale(locale: "tr-TR")
               .build()
)

📘

Tip

If you use the Translate option for Story Groups on the Storyly Dashboard, end user will see the content in their own locale.