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.

Embed Features

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)
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.
To do so, you'll need to first import the SDK using a <script> tag in the <head> of your HTML:
<!-- The rest of your head contents -->
<script src="https://sdk.monterosa.cloud/0.16.2/widget/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.2/widget/index.es5.js" defer="defer"></script>
-->
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.
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 GIT repository source URL to your Podfile
source 'https://<package username>:<package token>@gitlab.com/monterosa-sdk/ios-specs.git'
Add the required pods to your Podfile:
pod 'MonterosaSDKCore'
pod 'MonterosaSDKLauncherKit'
Add private Monterosa registry URL and credentials to the project-level settings.gradle
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)
}
}
}
}
Add the following Interaction SDK packages as dependencies to the app-level build.gradle:
dependencies {
...
implementation "co.monterosa.sdk:core"
implementation "co.monterosa.sdk:launcherkit"
...
}
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: You still 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>", project: "<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
await 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 experienceView = Launcher.default.getExperience(context)
root_container.addView(experienceView)
const experience = await getExperience();
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 experienceView = Launcher.default.getExperience(this)
experienceView.listener = this
root_container.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 experienceView = Launcher.default.getExperience(context, eventId)
root_container.addView(experience)
const eventId = '<event id>';
const experience = await getExperience(eventId);
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 experienceView1 = launcher1.getExperience(context)
val experienceView2 = launcher2.getExperience(context)
root_container.addView(experienceView1)
root_container.addView(experienceView2)
const sdk1 = await configure({
host: '<host 1>',
project: '<project 1>',
}, '<name 1>');
const sdk2 = await configure({
host: '<host 2>',
project: '<project 2>',
}, '<name 2>');
const experience1 = getExperience(sdk1);
const experience2 = getExperience(sdk2);
embed(experience1, '<container 1>');
embed(experience2, '<container 2>');

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.

Configuring your Experience

The SDK offers a simple interface that allows you to offer Experiences to your users in few lines of code.
You can also control and customise behaviour beyond the defaults. For example, an Experience can be configured to exist as an embed within a written article, rather like a widget. But you can also set the same Experience to display full page with its header and footer.
This section covers the available options.

Manage the Experience's size

By default, the SDK will respect the height specified within your application and display a scrollbar when necessary so the user can navigate the full content.
However, the SDK can automatically manage the height of the view for you, by respecting the width set and updating the height to match that of the content in the Experience:
Note: This feature only works on FanKit versions 24.33.0 or later
iOS
Android
JavaScript
let config = ExperienceConfiguration(
autoresizesHeight: true
)
let experience = Launcher.getExperience(config: config)
<yourView>.addSubview(experience)
// You need to ensure you layout the experience correctly using autolayout,
// but ensure you don't constraint yet the height of the view
// (or use a low priority constraint), as that will be managed by the SDK.
//
// For instance, to attach to the top, and both sides, start with
// 300px height, and eventually let the SDK manage the height,
// you'd use the following code:
experience.translatesAutoresizingMaskIntoConstraints = false
experience.topAnchor.constraint(equalTo: <yourView>.topAnchor, constant: 0).isActive = true
experience.leadingAnchor.constraint(equalTo: <yourView>.leadingAnchor, constant: 0).isActive = true
experience.trailingAnchor.constraint(equalTo: <yourView>.trailingAnchor, constant: 0).isActive = true
// Setting default low priority on the constraint so the height
// constraint set by the SDK overrules it.
let heightConstraint = experience.heightAnchor.constraint(equalToConstant: 300)
heightConstraint.priority = .defaultLow
heightConstraint.isActive = true
// Assumes `this` is an activity, otherwise update this line
// to locate the context you want to use.
val context = this
val config = ExperienceConfig(
autoresizesHeight = true
)
val experienceView = Launcher.default.getExperience(context, config)
root_container.addView(experience)
const exp = getExperience({
autoresizesHeight: true
});
embed(exp, 'container-id');
Additionally, we let you listen to changes in the intrinsic size of the web page, so you can handle the resize with your preferred approach:
iOS
Android
JavaScript
let experience = Launcher.getExperience()
// Assumes that we want to embed in the ViewController's view
// If you want to embed somewhere else use the relevant view instead
<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 `self` implements ExperienceViewDelegate
experience.delegate = self
// Example implementation of ExperienceViewDelegate
extension MyViewController: ExperienceViewDelegate {
// [...]
// Implementation of the rest of ExperienceViewDelegate
// [...]
func didChangeIntrinsicSize(experienceView: ExperienceView, size: CGSize) {
// Here you can update your size as needed
}
}
// Assumes `this` is an activity, otherwise update this line
// to locate the context you want to use.
val context = this
val experienceView = Launcher.default.getExperience(context)
experience.listener = object: ExperienceViewListener {
override fun onIntrinsicSizeChanged(experienceView: ExperienceView, width: Float, height: Float) {
// Here you can update your size as needed
}
}
const exp = getExperience();
embed(exp, 'container-id');
onIntrinsicSizeChanged(exp, (width, height) => {
// Here you can update your size as needed
});
Note: This feature only works on FanKit versions 24.33.0 or later
By default, the SDK assumes that the parent application will be displaying its own header and footer, and therefore we hide the Experience’s default header if one exists. You can override this behaviour and present the header and footer of the Experience by using the following snippet:
iOS
Android
JavaScript
let config = ExperienceConfiguration(
hidesHeadersAndFooters: false
)
let experience = Launcher.getExperience(config: config)
<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 = ExperienceConfig(
hidesHeadersAndFooters = false
)
val experienceView = Launcher.default.getExperience(context, config)
root_container.addView(experience)
const exp = getExperience({
hidesHeadersAndFooters: false
});
embed(exp, 'container-id');

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 experienceView = Launcher.default.getExperience(context)
// 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...
root_container.addView(experience)
Not yet available.

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.
You can use them by following the next snippets:
Activity
Fragment
val experienceIntent = Launcher.default.getExperienceIntent(context)
startActivity(experienceIntent)
val experienceFragment = Launcher.default.getExperienceFragment(context)
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)
experienceView.experienceOnTouchListener = View.OnTouchListener{ view, motionEvent ->
// React to touch events
}

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)
experienceView.allowFullScreenVideosInActivity(activity = this)

Shared storage in embedded Experiences

We also support a shared storage so that the Experience can access a data storage located on your application with ease. You have the option to choose between two types of storage: persistent or in-memory storage. This gives you more flexibility and control over how your users' data is stored.
The Experience won't request the user permission to store data, instead we expect you to set the storage in persistent mode only if you are certain you comply with all regulations required for the countries and regions you operate in.
By using the SDK, you can also improve the privacy and security of your users' data because you can choose the best way to store it according to your users' preferences, and needs.
If you enable persistent storage, the SDK will store data in the local storage of your webpage for JavaScript, or the application's sandbox for Android and iOS. This ensures that data will be available across multiple sessions. However, if you disable persistent storage, data will be stored in memory. This provides faster access but will not be available across multiple sessions.
iOS
Android
JavaScript
// Enable
experienceView.setPersistance(isGranted: true)
// Disable
experienceView.setPersistance(isGranted: false)
// Enable
experienceView.setStoragePersistent(true)
// Disable
experienceView.setStoragePersistent(false)
import { setStoragePersistent } from "@monterosa-sdk/launcher-kit";
// enable persistent storage
setStoragePersistent(true);
// disable persistent storage
setStoragePersistent(false);
Additionally, the SDK will ensure that data is transitioned seamlessly from persistent to in memory and back by copying the data available from memory to disk, and the other way around, so any change in configuration won't result in any data loss during your user's session.