v24
Ask or search…
K
Links

Embed Experiences using the SDK

How to embed Experiences into your products using Monterosa / Interaction SDK
Please contact our sales team if you're interested in access to the Monterosa / Interaction SDK v2.
The SDK can be used to embed an Experience into your web or native app. This provides loading and resizing capabilities which save you integration effort and make for a smooth user experience.
You can load any of the ready-made Experiences from the Experience Library or those that have been developed specifically for you and made available in the platform.
Using the SDK to embed Experiences is not mandatory, you can also deploy Experiences using custom code to manage loading and sizing.
Click here to see a working example of an Experience embedded using the SDK.

Why Embed with the SDK?

The SDK supports the following use cases:
  • Launch an Experience with a few lines of code
  • Dynamic resizing and self-managing size based on the needs of the Experience
  • Displaying or removing headers and footers depending on context
  • Preloading the Experience (native apps)
  • Supports sharing storage between your app and the Experience, ensuring a smooth experience for all users even in incognito windows.
You can use our demo page built with the SDK to see these features in action.
Subsequent releases will include additional support for:
  • Cookie consent management
  • Speeding up load times
  • Infinite scrolling

Getting started

You'll need to decide which integration method you want to use:
  • Static page embedding: This approach is the most straightforward manner to embed an Experience on your website, via HTML without any coding required.
  • Dynamically embedding in a web page or mobile app: This approach allows you more fine-tuned control over the integration, by letting you interact with the SDK using Javascript, Kotlin, or Swift, depending on your platform of choice.
Our recommendation is to favour the static embedding if you only will use the following features:
  • Embed an Experience
  • Fix the Experience on a specific Event
  • Autoresize heigh
  • Hide the header and footer of the Experience
If you need any further functionality, such as sharing data or session with the Experience, or passing parameters to it, you'll need to use the dynamic embedding approach.

Get the Experience's metadata

In order to embed an Experience, you'll need its Project ID and Static host. This information can be retrieved from Studio by navigating to the project, then accessing the API tab within the Settings section.
There you'll find a convenient way to copy the data you need:
Obtaining the project ID and host from Studio

Static embedding in a web page

If you are aiming for simplicity, you can embed an Experience using a declarative API. There are two primary methods for importing the SDK, each suitable for different use cases.

Step 1. Import the SDK

Choose one of the methods below to import the SDK into your web page. This step is crucial to ensure that the SDK is available for embedding the Experience.

Using a <script> tag in the <head> of your HTML:

This method is ideal for simpler applications. It’s a quick way to get started without setting up a JavaScript module bundler like Webpack or Babel.
<!-- The rest of your head contents -->
<script src="https://sdk.monterosa.cloud/0.16.11/static-embed/index.js" defer="defer"></script>
<!-- If you want to use ES5, you can instead using this script -->
<!-- script src="https://sdk.monterosa.cloud/0.16.11/static-embed/index.es5.js" defer="defer"></script-->

Importing as an npm module in your JavaScript code:

This approach is ideal for complex applications that utilise modern JavaScript bundling tools, allowing developers to integrate the SDK into a single JavaScript file alongside their code. This integration offers a seamless inclusion of the SDK within the application's build process.
import '@monterosa-sdk/widget';

Step 2. Embed Using Custom HTML Tag

Once you have imported our SDK, you can embed an Experience by using a custom HTML tag of type <monterosa-experience> anywhere in the <body> of your web page. Notice you must provide the host and project Id of the Experience you want to embed. It will not function properly without those parameters. Please read through our getting started to find out where to get them. For example:
<monterosa-experience
host="<host>"
projectId="<project id>"
>
</monterosa-experience>
For the Experience to be correctly embedded you'll need to serve your webpage via HTTP or HTTPS. Opening it as a file on your browser is currently not supported.

Step 3. Customising the Experience (optional)

In order to configure your Experience, the following attributes of the Experience tag can be customised:
  • host, specifies the host of the Experience (mandatory)
  • project, specifies the project of the Experience (mandatory)
  • eventId, specifies the event that will be displayed when more than one is present in the Experience. If left unspecified, the Experience will display content from all events.
  • autoresizesHeight when present, the Experience will autoresize its own height depending on the size needed by the Experience. This mirrors the behaviour of Manage the Experience's size.
  • hidesHeadersAndFooters, when present, the Experience will remove its own headers and footers to let you use your own instead.
Additionally, the Experience tag can be styled as any other HTML element, allowing you to further customise its look and feel.

Dynamic embedding in a web or application

Download and initialise 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:
If you're an existing customer and can't find your Welcome Pack, please raise a ticket via [email protected] or speak to your Account Manager.
iOS
Android
Javascript
If you use Swift Package Manager, add the following GIT repository URL as a new package dependency in Xcode:
https://<package-username>:<package-token>@gitlab.com/monterosa-sdk/ios.git
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.9"
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 => version
end
Add our private registry URL and credentials to the project-level settings.gradlewith your Gradle DSL of choice:
Kotlin DSL
Groovy
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://gitlab.com/api/v4/projects/38419902/packages/maven")
credentials(HttpHeaderCredentials::class.java) {
name = "Deploy-Token"
// The format of the token should be similar to: 'SC3hJTmsGtEJFpwk-XEU'
value = "<package token>"
}
authentication {
val header by registering(HttpHeaderAuthentication::class)
}
}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven {
url "https://gitlab.com/api/v4/projects/38419902/packages/maven"
credentials(HttpHeaderCredentials) {
name = 'Deploy-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:
Kotlin DSL
Groovy
plugins {
...
id("kotlin-parcelize")
}
...
dependencies {
...
// Ensure you are using the latest version
implementation("co.monterosa.sdk:core:0.16.11")
implementation("co.monterosa.sdk:launcherkit:0.16.11")
implementation("co.monterosa.sdk:interactkit:0.16.11")
implementation("co.monterosa.sdk:identifykit:0.16.11")
...
}
plugins {
...
id "kotlin-parcelize"
}
...
dependencies {
...
// Ensure you are using the latest version
implementation "co.monterosa.sdk:core:0.16.11"
implementation "co.monterosa.sdk:launcherkit:0.16.11"
implementation "co.monterosa.sdk:interactkit:0.16.11"
implementation "co.monterosa.sdk:identifykit:0.16.11"
...
}
And finally, add the following rule to your proguard-rules.pro file :
# Monterosa SDK rules
-keep class co.monterosa.sdk.** { *; }
-dontwarn java.lang.management.**
-dontwarn androidx.window.extensions.**
-dontwarn androidx.window.extensions.embedding.**
-dontwarn androidx.window.sidecar.**
You may need to invalidate Anroid Studio's cache if this error is raised:
Gradle sync (Failed to resolve: co.monterosa.sdk:{kit}:X.Y.Z and Failed to resolve: co.monterosa.sdk:{kit}:X.Y.Z).
To invalidate the cache you'll need to delete the cache folder, which is located at:
On Windows: %USERPROFILE%.gradle\caches
On Mac/UNIX: ~/.gradle/caches/
You can browse to these directory and manually delete it or run on your terminal:
rm -r $HOME/.gradle/caches/
After that use the Invalidate Caches / Restart option of Android Studio.
All Interaction SDK packages are scoped as @monterosa-sdk. Run the following NPM commands to tell NPM where to look for packages from that scope:
npm config set @monterosa-sdk:registry https://gitlab.com/api/v4/projects/38419920/packages/npm/
npm config set //gitlab.com/api/v4/projects/38419920/packages/npm/:_authToken "<package token>"
Finally, execute the following commands to install the required packages:
npm install @monterosa-sdk/core
npm install @monterosa-sdk/launcher-kit
npm install @monterosa-sdk/interact-kit
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.
iOS
Android
Javascript
import UIKit
import MonterosaSDKCore
@UIApplicationMain
class AppDelegate: UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
Core.configure(host: "<static host>", projectId: "<project id>")
...
}
}
class SampleApplication: MultiDexApplication() {
override fun onCreate() {
super.onCreate()
Core.configure(
context = this,
host = "<static host>",
projectId = "<project id>"
)
}
}
// 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 tag
configure({
host: '<static host>',
project: '<project id>'
});

Launch an Experience

All Projects are associated with an Experience, also known as an App. You can check Monterosa / Interaction Cloud core concepts if you need more information.
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:
iOS
Android
JavaScript
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 = false
experience.topAnchor.constraint(equalTo: <yourView>.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
experience.bottomAnchor.constraint(equalTo: <yourView>.bottomAnchor, constant: 0).isActive = true
experience.leadingAnchor.constraint(equalTo: <yourView>.leadingAnchor, constant: 0).isActive = true
experience.trailingAnchor.constraint(equalTo: <yourView>.trailingAnchor, constant: 0).isActive = true
val config = ExperienceConfiguration()
val experienceView = Launcher.default.getExperience(context, config)
root_container.addView(experienceView)
const experience = getExperience();
await embed(experience, 'container-id');
Then, simply place the Experience Object you've just created on the screen and it will initiate automatically.
In the Javascript SDK, the Experience 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.
iOS
Android
class MyViewController: UIViewController {
override func viewDidLoad() {
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
}
}
extension MyViewController: ExperienceViewDelegate {
func didStartLoading(experienceView: ExperienceView) {
displayLoadingUI()
}
func didEndLoading(experienceView: ExperienceView) {
hideLoadingUI()
}
func didFailLoading(experienceView: ExperienceView, error: Error) {
hideLoadingUI()
displayErrorUI(with: error)
}
// [...]
// Implementation of the rest of ExperienceViewDelegate
// [...]
}
class MyActivity : AppCompatActivity(), ExperienceViewListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
val config = ExperienceConfiguration()
val experienceView = Launcher.default.getExperience(this, config)
experienceView.listener = this
rootContainer.addView(experience)
}
override fun onStartLoading(experienceView: ExperienceView) {
displayLoadingUI()
}
override fun onEndLoading(experienceView: ExperienceView) {
hideLoadingUI()
}
override fun onFailLoading(experienceView: ExperienceView, error: Throwable) {
hideLoadingUI()
displayErrorUI(error)
}
}
Additionally you can launch a specific Event within your Experience using the following snippet:
iOS
Android
JavaScript
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
val eventID = "<event id>"
val config = ExperienceConfiguration(eventId = eventID)
val experienceView = Launcher.default.getExperience(context, config)
rootContainer.addView(experience)
const eventId = '<event id>';
const experience = getExperience({
eventId,
// Other ExperienceConfiguration values can be added,
// such as autoresizesHeight, hidesHeadersAndFooters, etc...
});
await embed(experience, 'container-id');

Launching multiple Experiences

In some cases you may find it useful to embed multiple Experiences 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 Experiences by allowing you to configure multiple SDK instances as long as you provide a unique name to identify them.
iOS
Android
JavaScript
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
Core.configure(
context = this,
host = "<host 1>",
projectId = "<project 1>",
name = "<name 1>"
)
val sdk1 = Core.core("<name 1>")
val launcher1 = Launcher.from(sdk1)
Core.configure(
context = this,
host = "<host 2>",
projectId = "<project 2>",
name = "<name 2>"
)
val sdk2 = Core.core("<name 2>")
val launcher2 = Launcher.from(sdk2)
val config = ExperienceConfiguration()
val experienceView1 = launcher1.getExperience(context, config)
val experienceView2 = launcher2.getExperience(context, config)
rootContainer.addView(experienceView1)
rootContainer.addView(experienceView2)
const sdk1 = configure({
host: '<host 1>',
project: '<project 1>',
}, '<name 1>');
const sdk2 = configure({
host: '<host 2>',
project: '<project 2>',
}, '<name 2>');
const experience1 = getExperience(sdk1);
const experience2 = getExperience(sdk2);
await embed(experience1, '<container 1>');
await embed(experience2, '<container 2>');
Note that when launching multiple experiences, it is necessary to configure Identify Kit for each individual experience.
See the section here

Configuring Identify Kit for multiple experiences

iOS
Android
JavaScript
class MyViewController: UIViewController {
override func viewDidLoad() {
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
// [...]
}
class MyActivity : AppCompatActivity(), ExperienceViewListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
// You need to ensure you have followed the Configure Multiple
// Experiences step
val 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
}
}
import { configure } from '@monterosa-sdk/core';
import {
setCredentials,
getIdentify,
getUserData,
} from '@monterosa-sdk/identify-kit';
const sdk1 = configure({ host: '<host 1>', projectId: '<project 1>' });
const sdk2 = configure({ host: '<host 2>', projectId: '<project 2>' });
const identify1 = getIdentify(sdk1);
const identify2 = getIdentify(sdk2);
await setCredentials(identify1, { token: '<token 1>' });
await setCredentials(identify2, { token: '<token 2>' });
const user1 = await getUserData(identify1);
const user2 = await getUserData(identify2);

Disposing of an Experience

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.

Customising an Experience

Preload the Experience

Note: This feature is not yet available in the Javascript SDK.
With the default implementation, the Experience will load when it is shown to the user, but if you are aiming to reduce the loading time, you can trigger proactive loading so that it’s ready to go when the user wants to see it. Use the following snippet:
iOS
Android
JavaScript
let experience = Launcher.getExperience()
// At this point the experience will already be loading in the background
// You could now store it in memory until you need to embed it in your UI.
// Please note that this may consume resources, so be careful about how many
// Experiences you preload.
// Eventually...
<yourView>.addSubview(experience)
// You need to ensure the experiences are laid out however you see fit.
// For instance, could use autolayout constraints, or setting
// their frame
// Assumes `this` is an activity, otherwise update this line
// to locate the context you want to use.
val context = this
val config = ExperienceConfiguration()
val experienceView = Launcher.default.getExperience(context, config)
// At this point the experience will already be loading in the background
// You could now store it in memory until you need to embed it in your UI.
// Please note that this may consume resources, so be careful about how many
// Experiences you preload.
// Eventually...
rootContainer.addView(experience)
Not yet available.

Caching the contents of the Experience on Android and iOS

The Experience builds on top of iOS' WKWebView and Android's WebView, and therefore will cache the content in the same manner as Safari or Google Chrome would.
It is also possible to cache the ExperienceView itself and re-use further down the line of the user flow. This can come in handy in scenarios where the same Experience may be displayed multiple times in the same session.
To do so, you'd need to keep a reference to the ExperienceView after using it, and adding that same instance to your view hierarchy.
Note that if another Experience has been displayed after caching the instance, and before re-using it, the session will have expired.
To avoid displaying the "Session closed" dialog during this scenario, it is possible to leverage the Communication Bridge to notify the Experience not to display it. Please get in touch with our Solutions Architecture team to design the flow of messages required.
In general, this is solved with two messages or requests:
  • One to notify the ExperienceView that it is moved to the background
  • Another to notify that it is moved back to the foreground, also called on first launch

Launching an Experience as an Android Activity or Fragment

Aiming to provide the most flexibility we can, we have also wrapped our ExperienceView in an Activity and Fragment so you can leverage all the functionality Android provides within those two classes.
When using ExperienceActivity and ExperienceFragment, custom loading and error view providers are not supported as we can't parcelise the provider functions.
Instead, use an ExperienceView, or wrap it with your own Fragment or Activity.
You can use them by following the next snippets:
Activity
Fragment
val experienceIntent = Launcher.default.getExperienceIntent(context)
startActivity(experienceIntent)
val experienceFragment = Launcher.default.getExperienceFragment(config)
supportFragmentManager.beginTransaction()
.replace(R.id.container, experienceFragment)
.commitNow()

Listening to touch events in the Experience on Android

If you want to react to how users scroll through the Experience, e.g. in order to collapse a toolbar, we offer the possibility to provide an OnTouchListener that forwards you the user interactions with the Experience. You can register it like so:
val experienceView = Launcher.default.getExperience(context, config)
experienceView.experienceOnTouchListener = View.OnTouchListener{ view, motionEvent ->
// React to touch events
}

Customising the URLSession used in iOS

Customising the URLSession in an iOS application allows you to adapt network requests to meet your app's specific needs.
By setting a custom URLSession instance to the URLSession.monterosaSDK, the SDK allows you to override the the URLSession that the SDK uses.
This allows to:
  • Control the timeout period
  • Control the caching
  • Meet network security requirements (such as disabling HTTP cache)
  • ...
In order to override the URLSession, you'll need to set the value like so:
import MonterosaSDKConnectKit
...
let config = URLSessionConfiguration.default
// Your customisations, e.g. disable caching:
config.urlCache = nil
URLSession.monterosaSDK = URLSession(configuration: config)
...
Note that the URLSession will be injected into the SDK kits as they are being created, so it's preferable to set this value before accessing any functionality. For instance, you should execute this before:
  • Setting credentials in IdentifyKit
  • Instantiating an ExperienceView
Additionally, this property can be modified before Core.configure is called, so the safest approach would be to set it before the SDK is initialised.

Hosting videos from Experience on fullscreen on Android

To enable an Experience to host videos full screen in Android, you'll need to provide an Activity instance following the next snippet:
val experienceView = Launcher.default.getExperience(context, config)
experienceView.allowFullScreenVideosInActivity(activity = this)

Configuring Permissions Policy for Embedded iFrames

When embedding an <iframe>, SDK allows to manage the permissions policy effectively. This policy dictates which features are available to the <iframe>, considering factors such as access to the device's microphone, camera, battery, web-sharing capabilities, and more, contingent on the origin of the request.
To establish a permissions policy for an <iframe>, you must define the required features within the allow parameter of the getExperience() function. This configuration is essential for ensuring that only authorised features are accessible through the <iframe>, enhancing security and user experience.
For instance, if embedding a YouTube player within an <iframe>, it's necessary to permit features like fullscreen and picture-in-picture. This can be achieved as demonstrated in the following code snippet:
import { getExperience } from '@monterosa-sdk/launcher-kit';
const experience = getExperience({
// Specify the features to allow in the iframe.
// In this case, enabling fullscreen and picture-in-picture modes.
allow: 'fullscreen; picture-in-picture',
// Set allowFullscreen to true to ensure compatibility
// with fullscreen mode in older browsers
allowFullscreen