Initial SDK Setup

Initial SDK Setup

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

👍

You can also check out the demo on GitHub

Storyly Demo for Swift

Storyly Demo for Objective-C

📘

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

🚧

Warning

Storyly SDK targets iOS 11 or higher.

📘

Tips

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

CocoaPods

Storyly SDK is available through CocoaPods. To integrate Storyly SDK into your Xcode project using CocoaPods, specify it in your Podfile:

use_frameworks!
pod 'Storyly'

Then run pod install.

❗️

Danger

Please note that you need to use Storyly with use_frameworks! option in Podfile. If you need to add it without using use_frameworks! option, add following lines to your Podfile before updating Pods or check Manual Installation.

dynamic_frameworks = ['Storyly', 'SDWebImage']
pre_install do |installer|
  installer.pod_targets.each do |pod|
    if dynamic_frameworks.include?(pod.name)
      def pod.dynamic_framework?;
        true
      end
      def pod.build_type;
        Pod::BuildType.dynamic_framework
      end
    end
  end
end

🚧

Warning

Please note that CocoaPods version should be 1.9+

Carthage

Storyly SDK is available through Carthage. To integrate Storyly SDK into your Xcode project using Carthage, specify it in your Cartfile:

binary "https://prod-storyly-media.s3.eu-west-1.amazonaws.com/storyly-sdk/Carthage/Storyly.json"
github "SDWebImage/SDWebImage" == 5.10.0

Then run carthage update --use-xcframeworks.

After, add the frameworks to your Xcode project: Go to targets and select your application. Click plus button from the Frameworks, Libraries, and Embedded Content section and add Storyly.xcframework and SDWebImage.xcframework. If you can't find it, add it from Add Other > Add files dialog. Frameworks will be located at Carthage/Build/.

🚧

Warning

Please note that Carthage version should be 0.38+

Swift Package Manager

Storyly SDK is available through SPM. To integrate Storyly SDK into your Xcode project using SPM, add and enter package repository in the Swift Packages tab of your project.

Manually

If you prefer not to use dependency managers, Storyly SDK releases are available through Storyly iOS SDK Releases.

  • Download and unzip both Storyly.xcframework and SDWebImage.xcframework files.
  • Add the frameworks to your Xcode project: Use Finder to drag them both Storyly.xcframework and SDWebImage.xcframework folders into your Xcode project and drop it onto your project in the Project navigator window.
  • Follow the prompts to copy items into the destination and to create folder references.

Add Storyly View

You need to import related modules to use Storyly:

import Storyly
@import Storyly;

You can add StorylyView from Storyboard or Programmatically. Please follow the next sections.

Add Storyly View from Storyboard

StorylyView extends UIView so that you can use inherited functionality as it is. So, you can add StorylyView to any of the appsStoryboards and XIB Files.

  • Add a UIView in your Storyboard(or XIB File)
  • Define Custom Class as StorylyView in Identity Inspector.
  • Set height to 120 is suggested for a better experience for the default size

Add Storyly View Programmatically

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

let storylyViewProgrammatic = StorylyView()
self.view.addSubview(storylyViewProgrammatic)
StorylyView *storylyViewProgrammatic = [[StorylyView alloc] init];
[self.view addSubview:storylyViewProgrammatic];

🚧

Warning

Please note that if you use Auto Layout Constraints, you need to set translatesAutoresizingMaskIntoConstraints=false

Initialize StorylyView

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

self.storylyView.storylyInit = StorylyInit(storylyId: STORYLY_INSTANCE_TOKEN)
self.storylyView.storylyInit = [[StorylyInit alloc] initWithStorylyId: 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 detail.

Configuration

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.

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.

self.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(font: UIFont(name: "Your_font", size: 40)!)
                        .build()
                )
                .setUserData(data: [String : String])
                .setLabels(labels: Set<String>?)
                .setCustomParameter(parameter: String?)
                .setLayoutDirection(direction: .LTR | .RTL)
                .setTestMode(isTest: true)
  							.setLocale(locale: String?)
                .setProductConfig(
                    config: StorylyProductConfig.Builder()
                        .setFallbackAvailability(isEnabled: true)
                        .build()
                )
                .setStorylyPayload(payload: String?)
                .setShareConfig(
                    StorylyShareConfig.Builder()
                        .setShareUrl(url: String)
                        .setFacebookAppID(id: String)
                        .build()
                )
                .build()
        )

Set up Delegate

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, user redirections, and user interaction.

📘

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.

// the class(indicated with self) extends StorylyDelegate
self.storylyView.delegate = self // Override event functions
// the class(indicated with self) extends StorylyDelegate
self.storylyView.delegate = self; // Override event functions

StorylyLoaded Event

This event will let you know that Storyly has completed its data operations, and the Story Group list has just been shown to the user. In addition to the list of Story Groups, the data source of these groups is provided. In order to be notified about this event, use the following example:

func storylyLoaded(_ storylyView: Storyly.StorylyView,
                   storyGroupList: [Storyly.StoryGroup],
                   dataSource: StorylyDataSource) {}
- (void)storylyLoaded:(StorylyView *)storylyView
       storyGroupList:(NSArray<StoryGroup *> *)storyGroupList
       dataSource:(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:

func storylyLoadFailed(_ storylyView: Storyly.StorylyView,
                       errorMessage: String) {}
- (void)storylyLoadFailed:(StorylyView *)storylyView
             errorMessage:(NSString *)errorMessage {}

Show/Hide Storyly

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 Swift

Storyly Demo for Objective-C

Show Storyly

2834

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

Add StorylyView to a UIViewController with parameter isHidden as true. 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 parameter isHidden to false.

📘

Event handling

storylyLoaded event triggers first for available cached Stories and second for request response with current Stories. Detailed information about Event Handling

extension ShowStorylyViewController: StorylyDelegate {
    func storylyLoaded(_ storylyView: Storyly.StorylyView,
                       storyGroupList: [Storyly.StoryGroup]) {
        if initialLoad {
            initialLoad = false
            storylyView.isHidden = false
        }
    }
}
- (void)storylyLoaded:(StorylyView *)storylyView
       storyGroupList:(NSArray<StoryGroup *> *)storyGroupList {
    if (!self.initialLoad) {
        self.initialLoad = true;
        [self.storylyView setHidden:NO];
   }
}

Hide Storyly

2858

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

Not to show already visible StorylyView bar, check if initially loaded and storyGroupList size. Set StorylyView property isHidden to false.

Loading cached Stories triggers storylyLoaded event before storylyLoadFailed event. Check for if the cache loaded and storyGroupList size. If the cache is not loaded set the StorylyView parameter isHidden to true.

📘

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.

extension HideStorylyViewController: StorylyDelegate {
    func storylyLoaded(_ storylyView: Storyly.StorylyView, storyGroupList: [Storyly.StoryGroup]) {
        initialLoad = true
    }

    func storylyLoadFailed(_ storylyView: Storyly.StorylyView, errorMessage: String) {
        if !initialLoad {
            self.storylyView.isHidden = true
        }
    }
}
- (void)storylyLoaded:(StorylyView *)storylyView
       storyGroupList:(NSArray<StoryGroup *> *)storyGroupList {
    self.initialLoad = true;
}

- (void)storylyLoadFailed:(StorylyView *)storylyView
             errorMessage:(NSString *)errorMessage {
    if (!self.initialLoad) {
        [self.storylyView setHidden:YES];
    }
}

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.

// the class(indicated with self) extends StorylyProductDelegate
self.storylyView.productDelegate = self // Override event functions
...
extension ViewController: StorylyProductDelegate {
    // Override event functions
}

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?(STRCart((items: [STRCartItem], totalPrice: Float, oldTotalPrice: NSNumber?, currency: String) ))

onFail

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

onFail(STRCartEventResult("Your Failed Message"))

Usage of storylyUpdateCartEvent

extension ViewController: StorylyProductDelegate {
     /*
     * 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
     *
     */
    func storylyUpdateCartEvent(storylyView: StorylyView, event: StorylyEvent, cart: STRCart?, change: STRCartItem?, onSuccess: ((STRCart) -> Void)?, onFail: ((STRCartEventResult) -> Void)?)
    {
     when (event){
                   StorylyEvent.StoryProductAdded -> {
                      print("Shopping StoryProductAdded")
                     //This event sent when a product is added.
                   }
                   StorylyEvent.StoryProductUpdated -> {
                      print("Shopping StoryProductUpdated")
                     //This event sent when a product is updated.
                   }
                   StorylyEvent.StoryProductRemoved -> {
                      print("Shopping StoryProductRemoved")
                     //This event sent when a product is removed.
                   }
                 }
      print("Shoppable ShoppableEvent: \(event)")
      print("Shoppable ShoppableCart: \(cart)")
      print("Shoppable ShoppableChange: \(change)")
      
      DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(2_000), execute: {
            onSuccess?(STRCart((items: [STRCartItem], totalPrice: Float, oldTotalPrice: NSNumber?, currency: String) ))
      })
      onFail(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

extension ViewController: StorylyProductDelegate {
    func storylyEvent(_ storylyView: StorylyView,
                      event: StorylyEvent,
                      product: STRProductItem?, extras: [String:String]) {
      when (event){
                    StorylyEvent.StoryCheckoutButtonClicked -> {
                        print("Shopping StoryCheckoutButtonClicked")
                    }
                    StorylyEvent.StoryCartButtonClicked -> {
                        print("Shopping StoryCartButtonClicked")
                    }
                    StorylyEvent.StoryCartViewClicked -> {
                        print("Shopping StoryCartViewClicked")
                    }
                    StorylyEvent.StoryProductSelected -> {
                        print("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.

extension ViewController: StorylyProductDelegate {
    /**
 * This function will notify you to products
 *
 * - Parameter storylyView: StorylyView instance in which the user interacted with a component
 * - Parameter productIds: Found product ids in stories
 */
func storylyHydration(_ storylyView: StorylyView, products: [STRProductInformation]) {
        print("storylyHydration, products: \(products)")
    }
}

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 storylyTestMode is false, you need to explicitly define to set test devices.

self.storylyView.storylyInit = StorylyInit(
            storylyId: storylyToken,
            config: StorylyConfig.Builder()
                .setTestMode(isTest: true)
                .build()
)

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:

self.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.