Use the flexible dynamic embedding to take further control
To use the dynamic embedding method follow this guide and the various operating system-specific behaviours.
Get the SDK
First, you'll need to configure your development environment to gain access to the SDK. You'll need the credentials included in your "Welcome pack" to achieve this. See also Download & Initialise the SDK
If you're an existing customer and can't find your Welcome Pack, please raise a ticket via support@monterosa.co or speak to your Account Manager.
If you use Swift Package Manager, add the following GIT repository URL as a new package dependency in Xcode:
Finally, select MonterosaSDKCore and MonterosaSDKLauncherKit from the list of available Package Products.
If you use CocoaPods, add the following to your app target in your Podfile
target 'MyApp'do username = "<YOUR USERNAME>" token = "<YOUR TOKEN>" version = "0.16.12" url = "https://#{username}:#{token}@gitlab.com/monterosa-sdk/ios.git" pod 'MonterosaSDKCommon',:git=> url,:tag=> version pod 'MonterosaSDKConnectKit',:git=> url,:tag=> version pod 'MonterosaSDKCore',:git=> url,:tag=> version pod 'MonterosaSDKLauncherKit',:git=> url,:tag=> version pod 'MonterosaSDKIdentifyKit',:git=> url,:tag=> versionend
Add our private registry URL and credentials to the project-level settings.gradlewith your Gradle DSL of choice:
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) repositories { google() mavenCentral() maven { url "https://gitlab.com/api/v4/projects/38419902/packages/maven" credentials(HttpHeaderCredentials) { name ='Private-Token'// The format of the token should be similar to: 'SC3hJTmsGtEJFpwk-XEU' value ='<package token>' } authentication { header(HttpHeaderAuthentication) } } }}
Update your module's build.gradle file so as to add the kotlin-parcelize and the following packages as dependencies:
plugins {...id("kotlin-parcelize")}...dependencies {...// Ensure you are using the latest versionimplementation("co.monterosa.sdk:core:0.16.13")implementation("co.monterosa.sdk:launcherkit:0.16.13")implementation("co.monterosa.sdk:interactkit:0.16.13")implementation("co.monterosa.sdk:identifykit:0.16.13")...}
plugins {... id "kotlin-parcelize"}...dependencies {...// Ensure you are using the latest version implementation "co.monterosa.sdk:core:0.16.13" implementation "co.monterosa.sdk:launcherkit:0.16.13" implementation "co.monterosa.sdk:interactkit:0.16.13" implementation "co.monterosa.sdk:identifykit:0.16.13"...}
And finally, add the following rule to your proguard-rules.pro file :
Important: The JavaScript SDK can only be run in a browser environment and is not intended to be used with Node.js.
You will also need to include all Stable polyfills for environments that don't support the features required by Monterosa / Interaction SDK.
Once you have access to the SDK, you'll have to configure it during the startup of your application, so it is able to access your project. For that, you'll need a static host and a project id, which can be retrieved in Studio.
// As soon as you can in the lifecycle of your application// E.g. this could be the root component of your ReactJS application// or in the first file you import with a <link> HTML tagconfigure({ host:'<static host>', project:'<project id>'});
Launch an App/Experience
All Projects are associated with an App, also known as an Experience.
You will need to obtain an Experience Object — a programmatic interface to the Monterosa / Interaction Cloud Experience you're launching — and then place it in your views:
let experience = Launcher.getExperience()<yourView>.addSubview(experience)// You need to ensure you layout the experience correctly// For instance, to display on full screen using autolayout,// you'll need something like this:experience.translatesAutoresizingMaskIntoConstraints =falseexperience.topAnchor.constraint(equalTo:<yourView>.safeAreaLayoutGuide.topAnchor, constant:0).isActive =trueexperience.bottomAnchor.constraint(equalTo:<yourView>.bottomAnchor, constant:0).isActive =trueexperience.leadingAnchor.constraint(equalTo:<yourView>.leadingAnchor, constant:0).isActive =trueexperience.trailingAnchor.constraint(equalTo:<yourView>.trailingAnchor, constant:0).isActive =true
val config =ExperienceConfiguration()val experienceView = Launcher.default.getExperience(context, config)root_container.addView(experienceView)
Then, simply place the Experience Object you've just created on the screen and it will initiate automatically.
In the Javascript SDK, the app will start loading as soon as embedded.
On Android and iOS, it will start loading as soon as created. Additionally, iOS's and Android's ExperienceViews can notify you when the loading of the page has completed, allowing you to add a loading state if you chose to.
classMyViewController:UIViewController {overridefuncviewDidLoad() { super.viewDidLoad()...let experience = Launcher.getExperience() experience.delegate = self... view.addSubview(experience)// You need to ensure the experience is laid out however you see fit.// For instance, could use autolayout constraints, or setting // its frame }}extensionMyViewController:ExperienceViewDelegate {funcdidStartLoading(experienceView: ExperienceView) {displayLoadingUI() }funcdidEndLoading(experienceView: ExperienceView) {hideLoadingUI() }funcdidFailLoading(experienceView: ExperienceView, error: Error) {hideLoadingUI()displayErrorUI(with: error) }funcdidBecomeReady(experienceView: ExperienceView) {// Called when Experience is ready to receive messages. }funcdidReceiveMessage(experienceView: ExperienceView, message: MessageData) {// Receive messages sent by Experience. }// [...]// Implementation of the rest of ExperienceViewDelegate // [...]}
classMyActivity : AppCompatActivity(), ExperienceViewListener {overridefunonCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)...val config =ExperienceConfiguration()val experienceView = Launcher.default.getExperience(this, config) experienceView.listener =this rootContainer.addView(experience) }overridefunonStartLoading(experienceView: ExperienceView) {displayLoadingUI() }overridefunonEndLoading(experienceView: ExperienceView) {hideLoadingUI() }overridefunonFailLoading(experienceView: ExperienceView, error: Throwable) {hideLoadingUI()displayErrorUI(error) }overridefunonReady(experienceView: ExperienceView) {super.onReady(experienceView)// Called when Experience is ready to receive messages. }overridefunonMessage(experienceView: ExperienceView, message: Message) {super.onMessage(experienceView, message)// Receive messages sent by Experience. }// The SDK provides this listener for errors and exceptions that occur // during runtime, outside of the normal lifecycle events. // Implementing this listener offers a strategic approach to error handling, // allowing for the presentation of user-friendly messages to users.overridefunonExperienceError( experienceView: ExperienceView, experienceViewException: ExperienceViewException ) {handleExperienceError() } }
Additionally you can launch a specific Event within your app using the following snippet.
let eventId ="<event id>"let config =ExperienceConfiguration(eventId: eventId)let experience = Launcher.getExperience(config: config)<yourView>.addSubview(experience)// You need to ensure the experience is laid out however you see fit.// For instance, could use autolayout constraints, or setting // its frame
consteventId='<event id>';constexperience=getExperience({ eventId,// Other ExperienceConfiguration values can be added, // such as autoresizesHeight, hidesHeadersAndFooters, etc...});awaitembed(experience,'container-id');
How to launch multiple Apps/Experiences
In some cases you may find it useful to embed multiple apps within your application. For example, if you have multiple games or shows you're covering and want each to have a vote associated with them, each set up to look differently in their own Project.
The SDK supports multiple apps by allowing you to configure multiple SDK instances as long as you provide a unique name to identify them.
Core.configure( host:"<host 1>", projectId:"<project 1>", name:"<name 1>")let sdk1 = Core.core(by:"<name 1>")let launcher1 =Launcher()sdk1!.register(kit: launcher1)let experience1 = launcher1.getExperience()Core.configure( host:"<host 2>", projectId:"<project 2>", name:"<name 2>")let sdk2 = Core.core(by:"<name 2>")let launcher2 =Launcher()sdk2!.register(kit: launcher2)let experience2 = launcher2.getExperience()let sdk2 = Core.configure( host:"<host 2>", projectId:"<project id 2>", name:"<name 2>")<yourView>.addSubview(experience1)<yourView>.addSubview(experience2)// You need to ensure the experiences are laid out however you see fit.// For instance, could use autolayout constraints, or setting // their frame
If you're embedding more than one app you'll need to set the credentials of each using the snippit below:
classMyViewController:UIViewController {overridefuncviewDidLoad() { super.viewDidLoad()...// You need to ensure you have followed the Configure Multiple// Experiences step experience1.identify.setCredentials(credentials: UserCredentials(token:"token1") experience2.identify.setCredentials(credentials: UserCredentials(token:"token2") experience1.identify.add(delegate: self) experience2.identify.add(delegate: self)... }}extension MyViewController: IdentifyKitDelegate {// [...]// Implementation of IdentifyKitDelegate// [...]}
classMyActivity : AppCompatActivity(), ExperienceViewListener {overridefunonCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)...// You need to ensure you have followed the Configure Multiple// Experiences stepval identify1 = IdentifyKit.from(sdk1)val identify2 = IdentifyKit.from(sdk2) identify1.credentials =Credentials("<token1>") identify2.credentials =Credentials("<token2>") identify1.add(object: IdentifyKitListener {... }) identify2.add(object: IdentifyKitListener {... })// Add experiences to respective root containers }}
Once the user is done with an Experience, you'll want to make sure that the resources used by the SDK are freed up. For instance, when they swap from one to another, or if they navigate back in your navigation hierarchy,
To do so, take the following steps:
Remove the ExperienceView from the parent view or DOM element
Ensure you don't have any reference to it in memory
Once you do that, the garbage collector or reference counter of your language of choice will take care of disposing of the memory used.