# Storyly SDK Storyly SDK is a cross-platform mobile and web integration framework that enables developers to embed vertical story experiences and interactive content into their applications. The SDK provides native implementations for Android (Java/Kotlin), iOS (Swift/Objective-C), React Native, Flutter, Web, and Xamarin platforms, allowing apps to display Instagram-like stories with rich interactive components including polls, quizzes, product catalogs, ratings, and e-commerce integrations. The SDK supports multiple content types including traditional story bars, vertical feeds, and moments (user-generated content). It offers extensive customization options for styling story groups, handling user interactions, managing product catalogs with shopping cart functionality, and tracking analytics events. The SDK communicates with Storyly's backend services using a unique `storylyId` token to fetch and display story content configured through the Storyly Dashboard. ## Basic Integration - Android (Kotlin) Initialize StorylyView with your instance token to display story groups in your Android application. ```kotlin import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.appsamurai.storyly.StorylyInit import com.appsamurai.storyly.StorylyView class BasicActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initialize via XML-defined view val storylyView = findViewById(R.id.storyly_view) storylyView.storylyInit = StorylyInit("YOUR_STORYLY_INSTANCE_TOKEN") // Or create programmatically val storylyViewProgrammatic = StorylyView(this) storylyViewProgrammatic.storylyInit = StorylyInit("YOUR_STORYLY_INSTANCE_TOKEN") binding.storylyViewHolder.addView(storylyViewProgrammatic) } } ``` ## Basic Integration - iOS (Swift) Initialize StorylyView with your instance token and set the rootViewController for proper modal presentation. ```swift import UIKit import Storyly class BasicViewController: UIViewController { @IBOutlet weak var storylyView: StorylyView! override func viewDidLoad() { super.viewDidLoad() // Initialize via Storyboard/XIB storylyView.storylyInit = StorylyInit(storylyId: "YOUR_STORYLY_INSTANCE_TOKEN") storylyView.rootViewController = self // Or create programmatically with Auto Layout let storylyViewProgrammatic = StorylyView() storylyViewProgrammatic.translatesAutoresizingMaskIntoConstraints = false storylyViewProgrammatic.storylyInit = StorylyInit(storylyId: "YOUR_STORYLY_INSTANCE_TOKEN") storylyViewProgrammatic.rootViewController = self view.addSubview(storylyViewProgrammatic) NSLayoutConstraint.activate([ storylyViewProgrammatic.leadingAnchor.constraint(equalTo: view.leadingAnchor), storylyViewProgrammatic.trailingAnchor.constraint(equalTo: view.trailingAnchor), storylyViewProgrammatic.topAnchor.constraint(equalTo: storylyView.bottomAnchor, constant: 10), storylyViewProgrammatic.heightAnchor.constraint(equalToConstant: 120) ]) } } ``` ## Basic Integration - React Native Use the Storyly component with event handlers to display and interact with stories in React Native applications. ```javascript import React from 'react'; import { SafeAreaView, View, StyleSheet } from 'react-native'; import { Storyly } from 'storyly-react-native'; const App = () => { return ( { console.log('Stories loaded:', event.storyGroupList.length); }} onFail={(event) => { console.log('Load failed:', event.errorMessage); }} onStoryOpen={() => { console.log('Story opened'); }} onStoryClose={() => { console.log('Story closed'); }} onPress={(event) => { console.log('Story pressed:', event.story.title); }} onUserInteracted={(event) => { console.log('User interacted with:', event.storyComponent.type); }} /> ); }; const styles = StyleSheet.create({ container: { flex: 1 }, storylyContainer: { height: 100, marginTop: 10 }, storyly: { height: '100%' } }); export default App; ``` ## Basic Integration - Flutter Create a StorylyView widget with platform-specific parameters and callback handlers. ```dart import 'package:flutter/material.dart'; import 'package:storyly_flutter/storyly_flutter.dart'; class StorylyDemo extends StatefulWidget { @override _StorylyDemoState createState() => _StorylyDemoState(); } class _StorylyDemoState extends State { late StorylyViewController storylyViewController; void onStorylyViewCreated(StorylyViewController controller) { storylyViewController = controller; } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Container( height: 120, child: StorylyView( onStorylyViewCreated: onStorylyViewCreated, androidParam: StorylyParam() ..storylyId = 'YOUR_STORYLY_INSTANCE_TOKEN' ..storyGroupSize = 'large', iosParam: StorylyParam() ..storylyId = 'YOUR_STORYLY_INSTANCE_TOKEN' ..storyGroupSize = 'large', storylyLoaded: (storyGroups, dataSource) { debugPrint('Loaded ${storyGroups.length} story groups'); }, storylyLoadFailed: (errorMessage) { debugPrint('Load failed: $errorMessage'); }, storylyEvent: (event, storyGroup, story, storyComponent) { debugPrint('Event: $event'); }, storylyActionClicked: (story) { debugPrint('Action clicked: ${story.actionUrl}'); }, storylyUserInteracted: (storyGroup, story, storyComponent) { debugPrint('User interacted: ${storyComponent?.type}'); }, ), ), ], ), ); } } ``` ## Event Handling - Android (Java) Implement StorylyListener interface to handle all story events including load, fail, show, dismiss, and user interactions. ```java import com.appsamurai.storyly.*; import com.appsamurai.storyly.analytics.StorylyEvent; public class EventHandlingActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_event_handling); StorylyView storylyView = findViewById(R.id.storyly_view); storylyView.setStorylyInit(new StorylyInit("YOUR_STORYLY_INSTANCE_TOKEN")); storylyView.setStorylyListener(new StorylyListener() { @Override public void storylyLoaded(@NonNull StorylyView storylyView, @NonNull List storyGroupList, @NonNull StorylyDataSource dataSource) { // Handle stories loaded Log.d("Storyly", "Loaded " + storyGroupList.size() + " groups"); } @Override public void storylyLoadFailed(@NonNull StorylyView storylyView, @NonNull String errorMessage) { Log.e("Storyly", "Load failed: " + errorMessage); } @Override public void storylyStoryShown(@NonNull StorylyView storylyView) { // Story modal opened } @Override public void storylyStoryShowFailed(@NonNull StorylyView storylyView, @NonNull String errorMessage) { Log.e("Storyly", "Show failed: " + errorMessage); } @Override public void storylyStoryDismissed(@NonNull StorylyView storylyView) { // Story modal closed } @Override public void storylyActionClicked(@NonNull StorylyView storylyView, @NonNull Story story) { // Handle CTA button or swipe-up action String actionUrl = story.getMedia().getActionUrl(); // Open URL or handle custom action } @Override public void storylyUserInteracted(@NonNull StorylyView storylyView, @NonNull StoryGroup storyGroup, @NonNull Story story, @NonNull StoryComponent storyComponent) { // Handle interactive component responses (quiz, poll, etc.) Log.d("Storyly", "Interacted with: " + storyComponent.getType()); } @Override public void storylyEvent(@NonNull StorylyView storylyView, @NonNull StorylyEvent storylyEvent, @Nullable StoryGroup storyGroup, @Nullable Story story, @Nullable StoryComponent storyComponent) { // Track analytics events } }); } } ``` ## Custom Theming - iOS (Swift) Customize story group appearance including colors, borders, and icon styling. ```swift import UIKit import Storyly class CustomThemeViewController: UIViewController { @IBOutlet weak var storylyView: StorylyView! override func viewDidLoad() { super.viewDidLoad() storylyView.storylyInit = StorylyInit(storylyId: "YOUR_STORYLY_INSTANCE_TOKEN") storylyView.rootViewController = self // Customize story group text color storylyView.storyGroupTextColor = UIColor(red: 240/255, green: 57/255, blue: 50/255, alpha: 1.0) // Customize icon background color storylyView.storyGroupIconBackgroundColor = UIColor(red: 76/255, green: 175/255, blue: 80/255, alpha: 1.0) // Customize border colors for seen story groups (gradient) storylyView.storyGroupIconBorderColorSeen = [ UIColor(red: 197/255, green: 172/255, blue: 165/255, alpha: 1.0), UIColor.black ] // Customize border colors for unseen story groups (gradient) storylyView.storyGroupIconBorderColorNotSeen = [ UIColor(red: 251/255, green: 50/255, blue: 0, alpha: 1.0), UIColor(red: 255/255, green: 235/255, blue: 59/255, alpha: 1.0) ] // Customize story header icon border storylyView.storyItemIconBorderColor = [ UIColor(red: 251/255, green: 50/255, blue: 0, alpha: 1.0), UIColor(red: 255/255, green: 235/255, blue: 59/255, alpha: 1.0) ] // Customize progress bar colors (gradient) storylyView.storylyItemProgressBarColor = [ UIColor(red: 251/255, green: 50/255, blue: 0, alpha: 1.0), UIColor(red: 255/255, green: 235/255, blue: 59/255, alpha: 1.0) ] } } ``` ## Custom Theming - React Native Configure story group appearance with styling props for size, colors, layout, and typography. ```javascript import React, { useRef } from 'react'; import { View, StyleSheet } from 'react-native'; import { Storyly } from 'storyly-react-native'; const CustomThemeStoryly = () => { const storylyRef = useRef(null); return ( ); }; const styles = StyleSheet.create({ container: { flex: 1 }, storyly: { height: 120 } }); export default CustomThemeStoryly; ``` ## Controller Methods - React Native Use ref methods to programmatically control story playback, navigation, and data management. ```javascript import React, { useRef } from 'react'; import { View, Button, StyleSheet } from 'react-native'; import { Storyly } from 'storyly-react-native'; const StorylyController = () => { const storylyRef = useRef(null); // Refresh stories from network const handleRefresh = () => { storylyRef.current?.refresh(); }; // Open specific story by deep link URI const openStoryByUri = () => { storylyRef.current?.openStory('storyly://story/abc123'); }; // Open specific story by IDs const openStoryById = () => { storylyRef.current?.openStoryWithId( 'story-group-id', // storyGroupId 'story-id', // storyId (optional) 'default' // playMode (optional) ); }; // Control playback const pauseStory = () => storylyRef.current?.pauseStory(); const resumeStory = () => storylyRef.current?.resumeStory(); const closeStory = () => storylyRef.current?.closeStory(); return ( { console.log(`Loaded ${storyGroupList.length} groups`); }} />