Android Custom Code In-App Templates
Learn how to create and manage Custom Code Templates for In-App messages using the CleverTap Android SDK.
Overview
With Android SDK 7.0.0 and above, the CleverTap platform supports displaying Custom Code In-App messages. This feature allows developers to customize how In-App notifications are configured. The SDK provides the following two types of customizable components:
- Templates
- Functions
Key Differences between Templates and Functions
- Templates can include action arguments, while Functions cannot.
- Functions can be used as actions; Templates cannot. Functions can be set as either of the following:
- Visual Functions can contain UI logic and will be part of the In-App queue.
- Non-Visual Functions are triggered directly upon invocation without UI logic.
Create Templates and Functions
Templates and Functions can be created through Builders supported in SDK's versions 7.0.0 and above. Each template includes a name, a set of arguments, and a presenter. The name and presenter are mandatory, and the template name must be unique within the application.
The template builders validate the definitions and raise a CustomTemplateException
if the template is invalid.
It is generally advised not to handle these exceptions, but to fix the definitions instead.
Arguments
Arguments are key-value pairs used to configure custom code templates and functions.
The supported argument types are:
- Primitives: Boolean, Byte, Short, Integer, Long, Float, Double, String. Each primitive must have a default valuet hat will be used if no other value is specified.
- Map: A collection of supported primitives containing keys as argument names.
- File: A file argument that is downloaded when the template is triggered.
- Action: An argument for an action. It can be a function or a built-in action such as close or open url.
Hierarchical Arguments
You can group arguments in two ways:
- By using a map argument
- By Including Group Name in the Argument’s Name With a Dot (.) Symbol
Both methods are treated the same way.
By Using a map
Argument
map
ArgumentMap<String, Object> map = new HashMap<>();
map.put("a", 5);
map.put("b", 6);
builder.mapArgument("map", map);
mapArgument(
name = "map",
value = mapOf (
"a" to 5,
"b" to 6
)
)
By Including Group Name in Argument’s Name With a Dot (.) Symbol
builder.intArgument("map.a", 5);
builder.intArgument("map.b", 6);
builder.intArgument("map.a", 5)
builder.intArgument("map.b", 6)
File and Action Type Arguments
- File and Action arguments cannot be used inside a Map.
- To include a File or Action argument in a group, the group name must be included in the argument's name, separated by a dot (.).
In case you want to add File or Action type arguments to a Map you have defined, you can do it using the dot symbol.
builder.fileArgument("map.fileArg");
builder.actionArgument("map.actionArg");
builder.fileArgument("map.fileArg")
builder.actionArgument("map.actionArg")
Example of Template and Function Creation
The following is an example code for creating Template and Function:
new CustomTemplate.TemplateBuilder()
.name("template")
.presenter(presenter)
.stringArgument("string", "Default Text")
.fileArgument("file")
.intArgument("int", 0)
.build();
template {
name("template")
presenter(presenter)
stringArgument("string", "Default Text")
fileArgument("file")
intArgument("int", 0)
}
Register Custom Code In-App Templates
You must register the custom templates before creating the CleverTapAPI
instance.
We recommend initializing this instance in the Application.onCreate()
method.
If your application uses multiple CleverTapAPI
instances, use CleverTapInstanceConfig
to specify the registration of eachCleverTapAPI
instance.
To register custom templates, use the CleverTapAPI.registerCustomInAppTemplates
method, which accepts a TemplatesProducer
containing the template definitions.
CleverTapAPI.registerCustomInAppTemplates(ctConfig ->
CustomTemplatesExtKt.templatesSet( // or create a Set<CustomTemplate> and add your templates
new CustomTemplate.TemplateBuilder()
.name("template")
.presenter(templatePresenter)
.stringArgument("string", "Text")
.build(),
new CustomTemplate.FunctionBuilder(false) // Check Visual vs Non-visual Functions in "Key Differences"
.name("function")
.presenter(functionPresenter)
.intArgument("int", 0)
.build()
));
CleverTapAPI.registerCustomInAppTemplates {
setOf(
template {
name("template")
presenter(templatePresenter)
stringArgument("string", "Text")
},
function(isVisual = false) { // Check Visual vs Non-visual Functions in "Key Differences"
name("function")
presenter(functionPresenter)
intArgument("int", 0)
}
)
}
Sync In-App Templates to Dashboard
Templates must be synced with the CleverTap dashboard to be available in campaigns. First, define and register all templates and functions in the SDK, then use theCleverTapAPI.syncRegisteredInAppTemplate
method to sync them.
Sync Caution
This sync function should only be used in debug builds with a test user. We recommend running this function only during template development and ensure that you remove it before release. Do not include this function in release builds.
Present Templates
When a custom template is triggered, its presenter is invoked. Depending on the template type, presenters must extend theTemplatePresenter
or FunctionPresenter
. Both presenters must implement the onPresent()
method to execute the template invocation and exhibit their customized UI logic. Additionally, TemplatePresenter
should implement the onClose()
method to handle the closing of templates.
All presenter methods provide a CustomTemplateContext
, that enables you to:
- Obtain argument values with
get*(String name)
methods. - Trigger actions by their name through
CustomTemplateContext.triggerActionArgument
. - Set the status of the template invocation using the
CustomTemplateContext.setPresented()
andCustomTemplateContext.setDismissed()
methods to inform the SDK about the current template invocation. A presented state means that the In-App is displayed to the user. A dismissed state means that the In-App has been dismissed and is no longer visible.
Example of Template Presenter
Following is an example of Template Presenter:
class MyTemplatePresenter implements TemplatePresenter {
@Override
public void onPresent(@NonNull CustomTemplateContext.TemplateContext context) {
// be sure to keep the context as long as the template UI is being displayed
// so that context.setDismissed() can be called when the UI is closed.
showUI(context);
context.setPresented();
}
@Override
public void onClose(@NonNull CustomTemplateContext.TemplateContext context) {
// close the corresponding UI
context.setDismissed();
}
}
MyTemplatePresenter: TemplatePresenter {
override fun onPresent(context: TemplateContext) {
// be sure to keep the context as long as the template UI is being displayed
// so that context.setDismissed() can be called when the UI is closed.
showUI(context)
context.setPresented()
}
override fun onClose(context: TemplateContext) {
// close the corresponding UI
context.setDismissed()
}
}
In-App Queue
When an In-App message is triggered, it is added to a queue based on its priority and displayed only after all previous messages have been dismissed. This queue persists across app launches, ensuring that messages are shown when possible. Custom code In-App messages follow the same logic—they are triggered only when their corresponding notification is next in the queue. However, the next In-App message is not displayed until the current template invokes CustomTemplateContext.setDismissed()
.
Single Visual Template Limitation
The SDK can only display one visual template or In-App message at a time. New messages cannot be shown until the current message is dismissed.
File Downloading and Caching
File arguments are automatically downloaded and are ready for use when a template is displayed. Files are downloaded when a file argument changes and is not already cached.
File downloading occurs only before presenting the In-App. If any file argument fails to download, the In-App message is skipped, and the template is not triggered.
Updated about 4 hours ago