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
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 isYou 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
π!
Warning
While initializing the
StorylyView
, extra settings should be done withConfig
parameter. The aim is to gather all of the listed methods under theConfig
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 withConfig
parameter. The aim is to gather all of the listed methods under theConfig
parameter.
Configuration
Config
parameter includes all of the features and functionalities listed below:
- UI Customizations
- Targeting with Custom Parameter & Labels
- Personalization with Custom Parameter & User Properties
- Layout Direction
- Brand Domain Usage
- Shoppable Stories with Product Catalog
- Test Mode
- Localization
- Sharing Stories
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) {}
storylyActionClicked Event
This guide shows how to handle Swipe Up
and Action Button
clicks from user.
When the end-user clicks on the Swipe Up
or Action Button
, redirection needs to be handled by the application itself. In order to handle this action, you must register StorylyListener
and override storylyActionClicked
function in it. You can register the listener using the following code example:
storyly_view.storylyListener = object : StorylyListener {
override fun storylyActionClicked(storylyView: StorylyView, story: Story)
{
// story.actionUrl is important field
}
}
storyly_view.setStorylyListener(new StorylyListener() {
@Override
public void storylyActionClicked(@NonNull StorylyView storylyView,
@NonNull Story story)
{
// story.media.actionUrl is important field
}
});
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
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 beforestorylyLoadFailed
.
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 underchange.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
.
Updated 4 months ago