Use the flexible dynamic embedding to take further control
Last updated
Was this helpful?
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 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 => version
end
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 = uri("https://gitlab.com/api/v4/projects/38419902/packages/maven")
credentials(HttpHeaderCredentials::class.java) {
name = "Deploy-Token"
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 = '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 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")
...
}
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 :
// 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 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 = 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)
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.
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)
}
func didBecomeReady(experienceView: ExperienceView) {
// Called when Experience is ready to receive messages.
}
func didReceiveMessage(experienceView: ExperienceView, message: MessageData) {
// Receive messages sent by Experience.
}
// [...]
// 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)
}
override fun onReady(experienceView: ExperienceView) {
super.onReady(experienceView)
// Called when Experience is ready to receive messages.
}
override fun onMessage(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.
override fun onExperienceError(
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
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');
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
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)
Note that when launching multiple experiences, it is necessary to configure Identify Kit for each individual experience.
How to configure Identify Kit for multiple apps
If you're embedding more than one app you'll need to set the credentials of each using the snippit below:
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
}
}
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.
You will also need to include all 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 .
You can check Monterosa / Interaction Cloud and read about if you need more information.
On Android and iOS, it will start 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.