Userlike Bot Language

Chatbots can assist your team and take over boring and repetitive tasks such as gathering contact information, allowing your operators to focus on helping customers. They can also be useful as a way to answer simple questions after hours.
At Userlike, we believe in the power of human-to-human contact, but recognize the value service-bots can bring to messaging. This is why we offer the possibility to either integrate your own chatbot with our API or to create rule-based bot flows written in the Userlike Bot Language (UBL, covered in this tutorial).
This tutorial walks you through all the details for setting up your own bots within Userlike.

What is UBL?

The Userlike Bot Language (UBL) allows you to write bot scripts that can be used in your Widget and channels using a simple, minimal syntax.

YAML

UBL scripts are written with the YAML language. If you are not familiar with the YAML syntax, we suggest you read up on it first, as the rest of this tutorial assumes basic knowledge of YAML formatting and data types.
The basic layout of a UBL script looks as follows (each line is annotated with an explanatory comment):
yaml
-- # document start config: # A key with the name 'config', containing configuration information for your script abort: # A map with the key 'abort', this contains a map with a list of keywords that will immediately stop the conversation flow keywords: - stop skip: # A map with the key 'skip', this contains a map with a list of keywords that will skip optional inputs keywords: - skip # ^^^^ All your scripts should start with the block above 0: # Each conversation step has a unique key that is used to identify it. The first step MUST be an integer with the value 0 messages: # This is a node of the type 'message' - "Hello!" # The contents of the 'message' node is a sequence (list/array) of messages your want the bot to send - "I am a bot!" action: # An action is required in order to move to the next step next: 1 # In this case, it's a key-value pair pointing to the next step with the key 1 1: # You MUST use integers to identify your steps input: # This is a node of the type 'input'. It's a map with key-value pairs determining its content and behavior message: "What is your name?" type: text optional: false when: valid: messages: - "Thank you!" action: next: 2 2: messages: - "That's all for now!" action: end: true # Call the 'end' action when your conversation flow has reached the end to signal that the conversation should not go on
Your UBL file should always start with a config key containing essential configuration information for your script. config should contain an abort and a skip parameter. The keywords you define here will be used to trigger the abort sequence, which allows the contact to immediately quit the bot flow, or to skip input steps you‘ve defined as optional.
yaml
-- config: abort: # Define the keyword(s) that should immediately stop the conversation keywords: - stop # If the contact uses the word "stop" during any input step, the conversation is immediately forwarded action: # Defines the action to perform when the abort keyword is encountered. In this case the conversation is immediately forwarded forward_any: true skip: # Define the keyword(s) that should skip optional input steps keywords: - skip # [...the rest of your bot flow]

Script linting and validation

Once you've written a script you are happy with, you can upload it to Userlike and use it with your chatbots (further information in section below).
We will only apply basic linting to catch syntax errors when uploading the script. We do not validate your script for logic errors, such as conversation paths that lead to a dead end or infinite conversation loops. We recommend you test your scripts in a separate widget before going live with them.
Please make sure to use spaces for indentation, as tabs will be rejected during validation when uploading your script.

Testing your script

After uploading the script to Userlike, you are ready to test it. To do so, go to a page that contains the Widget you‘ve associated your chatbot with and start a conversation. Test all conversation paths and see if the conversation flow works as expected. If you discover something that needs adjustments, just open your .yml file in your favorite text editor, make adjustments and upload it again to test your changes.

Chatbot setup in Userlike

In Userlike, bots are a special type of operator. You can create a new chatbot by going to Team > Chatbots in your Dashboard. Click on Add chatbot to create a new chatbot.
Image without caption
Image without caption

Approach modes

There are four approach modes that you can select for your chatbot, depending on how you want to use it to provide service to your contacts:
  • Service time: The bot is online only outside of the services times defined in the Widget.
  • Backup: The bot is always online, but only takes conversations when no human operators are available for live conversations.
  • Human: The bot is always online and takes chats like any other operator.
  • Firewall: The bot is always online and receives all incoming conversations (eg. to pre-categorize and forward them)

Registration Mode

If a conversation with the bot starts from a widget that also has registration mode enabled, show the registration card. If this is not activated, we skip the registration for bots.

Bot conversation timeout

Define a time with no reply from both contact and bot after which the conversation is considered inactive. Once this happens, the bot can perform one of the following actions:
  • End conversation and move it to All conversations
  • Unassign conversation and move it to the Inbox, where any operator in your group can see and answer it.
  • Forward conversation to an available human operator from the same group.
Note that bot conversations don’t show up in your Inbox as long as they’re active. Your operators will only be able to see them once they end, are unassigned or forwarded.

Script upload

At the bottom of the Chatbot edit page you can insert your script into the integrated editor. Please use valid YAML code.
Image without caption

Nodes

You can use a number of possible elements to define the flow of a conversation with your bot. Nodes are conversation elements. Different types of nodes can be used to gather and validate data, display information and even talk to external APIs to send or retrieve information from third-party systems.

Config node

This is a mandatory node for every script. There you have to define the following options:
Option
Explanation
abort
Define keywords or phrases which get compared to a contacts input and abort the conversation on match. Optionally you can define a node, that should be processed before the conversation gets aborted.
skip
Define keywords or phrases which get compared to a contacts input. On a match, the current input node will be skipped. Only works on input nodes where the option optional is set to true. (link)
message_text_format (optional)
Set the text format of messages for the following nodes: - Message node - Input node - Bubbles node - Carousel node - List template node - Button template node The text format setting also applies to notes that are created for conversations by the command note_create. Allowed values: - plain_text - markdown_v1 When setting to markdown_v1, we will interpret the messages and notes in markdown. This allows you to send formatted texts across all channels. Please note that channels support only a certain set of formatting options individually. Also see here for more information on text formatting.
yaml
config: abort: keywords: - stop - cancel action: next: 100 skip: keywords: - skip message_text_format: markdown_v1

Global nodes

Global nodes allow you to match user messages throughout a conversation, no matter which node is currently active. For example, whenever a contact sends the text agent, the contact will be forwarded to human operators, if they are stuck somewhere in the flow. Global nodes are independently defined, which means they are not part of the standard conversation flow definition.
Additionally to contact messages, also clicked options texts from input bubbles / carousels and button texts from list and button templates are matched.
Please also see a full example here.
Skip Comparison on regular nodes
There might come up a situation when you don't want the contact message to be compared to the defined keywords and phrases for global nodes while a regular input node is active. For example when asking the user for a name or other input matching.
You can disable this behavior by setting the option `ignore_global_nodes: true` on the regular node.
Constraints
  • While a global input node is active any contact message will not be compared with other global node keywords or phrases.
  • Keywords from global nodes, or skip and abort configurations are not allowed to overlap.
yaml
global_nodes: offer_help: keywords: - help me! - help - ask for help # begin normal definition of a node. # Everything of what a regular node is capable of. input: message: "How can i help you?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 0 options: - option: "Questions about the product" messages: - "Ok, i will forward you to our Support department" action: forward_group: "Support" - option: "I have no further questions" messages: - "Have a nice day" action: end: true

Conditional node

These type of nodes allows you to control the flow of your chatbot based on various contact and conversation field values, such as: conversation topics, language, contact’s customer ID, current conversation context, custom fields, etc.
Let’s dive into a short example and go through step-by-step:
yaml
# Conditional node to change flow of the conversation bases on the contact customer ID 1: conditional: fallback: # mandantory fallback definition; called when no condition were met action: next: 100 actions: # 1st action - next: 200 # go to node 200 if this condition is met conditions: - type: comparison where: contact field_id: external_custom_id operand: regex compare_value: \\^eu_\d+ # match external_customer_id starting with 'eu_' # 2nd action - next: 300 # go to node 300 if this condition is met conditions: - type: logical # all conditions in operand: and conditions: - type: comparison where: contact field_id: external_custom_id operand: regex compare_value: \\^usa_\d+ # match external_customer_id starting with 'usa_' - type: comparison where: contact field_id: postcode operand: eq compare_value: "xzy"

Description: fallback

yaml
1: conditional: fallback: action: next: 100
Each conditional node needs to contain a fallback. The fallback contains instruction for the bot what to do if none of the checks returned a positive result. Since fallback works like a node, you can use any valid type of nodes inside fallback you find in this documentation. In our example, we call the action command next to immediately jump to the node 100.

Description: actions

yaml
actions: - next: 200 conditions: - ...
Actions is a list of objects with the following structure:
Parameter
Value
Description
conditions
list[condition]
A list of conditions to be evaluated.
next
int
The node which should be called next if the conditions are met by the match rule.

Description: conditions

yaml
# comparison conditions: - type: comparison where: contact field_id: external_custom_id operand: gte compare_value: 50670 # logical condition with multiple comparisons conditions: - type: logical operand: and conditions: - type: comparison where: contact field_id: external_custom_id operand: eq compare_value: "50670" - type: comparison where: contact field_id: postcode operand: eq compare_value: "12345"
Conditions is a list of objects where each object can be either a logical condition or a comparison condition determined by the key type:

Condition: type: logical

Parameter
Value
Description
type
"logical"
operand
string
The operand to connect the conditions with. Allowed values: - and - or
conditions
list[conditions]
A list of logical or comparison condition objects

Condition: type: comparison

Parameter
Value
Description
type
"comparison"
where
string
On which object to look-up the given field_id Allowed values: - contact - conversation - converstion_custom_fields - contact_custom_fields - context
field_id
string
Field name to get the value from by the given object from where key. (TODO: refer to JSON API for avaiable fields per object?)
operand
string
The operand to evaluate the field value with the compare value. Allowed values: - eq (equal) - neq (not equal) - in (value exist in a list) - not_in (value not exist in a list) - gte (greater than, equal) - lte (lesser than, equal) - regex (regex match) - not_regex (regex does not match)
compare_value
string / integer / null
The value you want to compare the field value with.

Multiple comparison conditions

When you define multiple comparison conditions in a list, then we automatically evaluate them by their order and return true by the first met condition.
yaml
# multiple comparison conditions: - type: comparison where: contact field_id: external_custom_id operand: eq compare_value: 50670 - type: comparison where: contact field_id: external_custom_id operand: eq compare_value: 60670 - type: comparison where: contact field_id: external_custom_id operand: eq compare_value: 60670
By this means, this has the same effect like using a logical 'or' condition beforehand. The next example has the same implications, as the one above.
yaml
# multiple comparison with a logical node `or` conditions: - type: logical operand: or conditions: - type: comparison where: contact field_id: external_custom_id operand: eq compare_value: 50670 - type: comparison ...

Message node

This is the simplest node type. The message node can be used to display text or send links to the contact. It also supports variable expansion, so it can be used to address the contact with their name, for example. Variables are expanded by wrapping them in double curly braces.
Example of a message node:
yaml
# Message node with a single message 1: # Conversation step messages: # Node type - "Single message" # A sequence with a single message action: # Next action next: 2 # Message node with a multiple messages 1: # Conversation step messages: # Node type - "First message" # Each message in this sequence will be sent to the contact separately - "Second message" action: # Next action next: 2 # Message node with a multiple messages and links 1: # Conversation step messages: # Node type - "Visit https://www.userlike.com !" # Each message in this sequence will be sent to the contact separately - "https://www.example.com" action: # Next action next: 2 # Assuming the contact provided his name and email, you can use this information in a message by expanding the name and email variables 1: messages: - "Welcome to the chat, {{name}}!" - "Your email address is {{email}}" action: next: 2

Media node

This is the node type displays media types like images and videos.
Example of a media node:
yaml
# Media node with a single item 1: # Conversation step messages: - "A picture" media: # Node type - option: link: "https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg" mime_type: "image/jpeg" action: # Next action next: 2 # Media node with a multiple items 1: # Conversation step media: # Node type - option: link: "https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg" mime_type: "image/jpeg" - option: link: "https://d3upe020n1uosc.cloudfront.net/static/web/videos/screencast-fullhd.mp4" mime_type: video/mp4 action: # Next action next: 2

Button node

This is the node type to display buttons with clickable links. It also supports variable expansion, so it can be used to address the contact with their name, for example. Variables are expanded by wrapping them in double curly braces.
Example of a button node:
yaml
# Button node with a single button 1: # Conversation step buttons: # Node type - label: "Send email to {{name}}" link: "mailto:{{email}}@userlike.com" action: # Next action next: 2 # Button node with multiple buttons 1: # Conversation step messages: - "We’re happy to help you!" buttons: # Node type - label: "Email" link: "mailto:support@userlike.com" - label: "Website" link: "https://www.userlike.com" - label: "Phone" link: "tel:+4922163060570" - label: "Whatsapp" link: "https://api.whatsapp.com/send?phone=4915735998856" action: # Next action next: 2

Input node: Text

There are different types of input nodes which represent the different ways you can collect information from your contacts. The text input node is a simple way to get data from your contact by asking them to enter text into the messenger input. The text input node has several parameters that can be used to make input required or handle invalid input. For example:
Parameter
Value
Description
message
string
A string containing the text you want to prompt the contact for input with.
type
text
Defines the input node as being of the type text
optional
boolean
Whether the input step can be skipped or not by not providing a value, or when the skip keyword is triggered.
key
string
The variable name the input text should be saved to.
when
skip / valid / exists
Determines what should happen when the condition defined by the value is met.
Example of a text input node in which we'll also introduce the exists parameter (which will be explained further in this tutorial):
yaml
# Asking for information (mandatory) 1: input: message: "What's your name?" type: text key: name optional: false when: valid: # In case the input is valid proceed to the next node messages: - "Thank you!" action: next: 2 exists: # If the 'name' variable already exists on the contact, we don't need to ask for it and can skip to the next step where: contact action: next: 2 # Asking for information (optional) 1: input: message: "What's your name?" type: text key: name optional: true when: valid: messages: - "Thank you!" action: next: 2 skip: # When the input is optional and the skip keyword is provided, the action defined under "skip" is performed. action: next: 3

Input node: bubbles

The bubble input node can be used to present the contact with multiple options to choose from. It displays them as buttons (or 'bubbles') that can be clicked by the contact. Alternatively, they can also choose an option by entering a number corresponding to one of the choices. For channels that don't support displaying bubbles, a text fallback can be defined which will be displayed instead.
The bubble input node is useful if you want to guide the contact closely along a determined conversation path by proposing a set of options to choose from.
Image without caption
Image without caption
Parameter
Value
Description
message
string
A string containing the text you want to prompt for input with.
type
bubbles
Defines the input node as being of the type bubbles
fallback
string
A string containing the text you want to display when bubbles cannot be displayed.
any_message
A node and action to perform
Determines what should happen when none of the options is chosen by the contact or any text is entered instead.
options
option
options should be a sequence of maps containing the text to display in the button under the key option and which action should be taken when the option is selected.
A simple example:
yaml
0: input: message: "Select an option" type: bubbles fallback: "Please enter a number" any_message: messages: - "That's not right, try again." action: next: 0 options: - option: "Option One" action: next: 1 - option: "Option Two" action: next: 2

Input node: carousel

The carousel input node is similar to the bubble input node in how it allows you to present a variety of choices that can be clicked by the contact. Instead of only presenting bubbles that can be clicked, the carousel node allows you to add an image and to add a headline and description to each option. The carousel node is perfect for providing the contact with a selection of items, for example in an online store.
Image without caption
Parameter
Value
Description
message
string
A string containing the text you want to prompt for input with.
type
carousel
Defines the input node as being of the type carousel
fallback
string
A string containing the text you want to display when carousel cannot be displayed.
any_message
A node and action to perform
Determines what should happen when none of the options is chosen by the contact or any text is entered instead.
options
option
options should be a sequence of maps containing the text to display in the button under the key option and which action should be taken when the option is selected.
The option map in the carousel node is slightly more complex than that of the bubble node. We've annotated the possible keys in the example below:
yaml
0: input: message: "Which car are you interested in?" type: carousel fallback: "Please enter a number" any_message: messages: - "Enter a number" action: next: 0 options: - option: headline: "Truck" # The headline or title of the item media: "https://url-to-picture..." # Provide the URL to the media you want to link, such as a .png file subheadline: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ultricies blandit magna, nec convallis leo eleifend quis." # The description of your item action: # What should happen when the user clicks on this item next: 1 - option: headline: "SUV" media: "https://..." subheadline: "Lorem ipsum..." action: next: 2

Input node: regex

Here's how you would use the regex input node:
yaml
# Input optional 1: input: message: "What's your tracking ID?" type: regex format: "[0-9]{6}-[0-9]{2}" key: tracking_id optional: true when: not-valid: messages: - "The format is not valid, please use 123456-12" - "Let's try again..." action: next: 1 valid: messages: - "Thank you." action: next: 2 skip: action: next: 2 # Phone number required 2: input: message: "What's your phone number?" type: regex format: "\\+49[0-9]{3,5}[0-9]{7,10}" key: phone_number optional: false when: not-valid: messages: - "The format is not valid, please use +4917212345678" - "Let's try again." action: next: 2 valid: action: next: 3
💡
Remember that the regular expression you provide to the format parameter will determine whether the input is considered valid or not. We do not check whether the regex provided here is correct, so we recommend checking its syntactic validity beforehand.
Parameter
Value
Description
message
string
A string containing the text you want to prompt the contact for input with.
type
regex
Defines the input node as being of the type regex
format
A valid regular expression
Provide the regular expression that should be matched in order for the input to be considered as valid.
optional
boolean
Whether the input step can be skipped or not by not providing a value, or when the skip keyword is triggered.
key
string
The variable name the input should be saved to.
when
skip / valid / not-valid / exists
Determines what should happen when the condition defined by the value is met.
This is a type of text input node that offers validation. Whereas the Email node can only validate email addresses, the Regex node allows you to provide a Regular expression to validate the data provided. This means it can be used for a wide range of applications, from making sure that a phone number matches a certain format to asking for dates, customer IDs or tracking numbers.

Input node: Email

Here's how you would use a simple email input node. As you can see, it's also possible to check if an email is already known for the contact:
yaml
1: input: message: "What's your email address?" type: email key: email optional: true when: not-valid: messages: - "The email format is not valid" - "Let's try again..." action: next: 1 valid: action: next: 2 skip: action: next: 3 exists: where: contact action: next: 2
Parameter
Value
Description
message
string
A string containing the text you want to prompt the contact for input with.
type
email
Defines the input node as being of the type email
optional
boolean
Whether the input step can be skipped or not by not providing a value, or when the skip keyword is triggered.
key
email
The email variable name the input should be saved to.
when
skip / valid / not-valid / exists
Determines what should happen when the condition defined by the value is met.
This node is a text input node with built-in validation for email addresses. You can use the email input node to ask your contacts to provide their email address. It will automatically check if the input provided is a valid email address. Unless you make the input optional, the contact won‘t be able to proceed to the next conversation step until a valid email address is provided. As you can see in the table below, it is very similar to the text input node. It has an additional not-valid condition that is triggered when the email address provided cannot be validated.

The exists logic

Here's an example of how an exists check would be performed on the contact's name:
yaml
# Checking if contact name exists 1: input: message: "What's your name?" type: text key: name optional: false when: # [...other parameters such as 'valid'] exists: # Checks if the key 'name' already contains data where: contact # where to check for the existence of 'name' messages: # We can use the variable in a message node - "Welcome back, {{name}}!" action: # What to do next, eg. skip gathering further contact info next: 6
As we've seen in the example above, we have the ability to check for the existence of a value and trigger an action accordingly.
The exists parameter itself needs the argument where, which can have a value of either contact or context, depending on where the information is stored.

Input node: list template

The list template input node is intended primarily for WhatsApp, though a reduced version of it will work on other channels. It is is similar to the bubble input node in that it allows you to display a variety of choices that can be clicked by contacts, but allows more extensive formatting options.
This is useful to display a larger list of up to ten options for the user to select from.
Image without caption
Image without caption
Parameter
Value
Description
message
string
A string containing the text you want to prompt for input with.
type
list_template
Defines the input node as being of the type list_template
fallback
string
A string containing the text you want to display to contacts when list_template cannot be displayed fully, i.e. when used on an unsupported channel.
any_message
A node and action to perform
Determines what should happen when contacts choose none of the options or enter text instead.
header
String
Optional headline displayed above the message, <= 60 chars.
list_header
String
Optional headline displayed in the select menu, <= 24 chars.
footer
String
Optional footer displayed below the message, <= 60 chars.
button_text
String
Text displayed on the button prompting the user to select something from the list, <= 20 chars.
options
option
options should be a sequence of maps, each one under the key “option”, with <= 10 options. The sequence can contain: - action: Action that should be taken when the option is selected - label: Main text on the element to select, <= 24 chars - description: Optional description text, <= 72 chars
A simple example:
yaml
0: input: message: "This is a list template. Please select something" type: list_template key: select fallback: "Please enter a number" header: "Header" list_header: "List header" footer: "Footer" button_text: "Click" any_message: messages: - "That's not right, try again." action: next: 0 options: - option: label: "Option One" description: "first option" action: next: 1 - option: label: "Option Two" description: "second option" action: next: 2 - option: label: "Option Three" description: "third option" action: next: 3 - option: label: "Option Four" description: "fourth option" action: next: 4

Input node: button template

The button template input node is intended primarily for WhatsApp, though a reduced version of it will work on other channels. It is similar to the bubble input node in that it allows you to display a variety of choices that can be clicked by contacts, but allows more extensive formatting options.
A button template allows you to display a few buttons combined with other content, like text and media files. Note that only up to three buttons are supported.
Image without caption
Parameter
Value
Description
message
string
A string containing the text you want to prompt for input with.
type
button_template
Defines the input node as being of the type button_template
fallback
string
A string containing the text you want to display to contacts when button_template cannot be displayed fully, i.e. when used on an unsupported channel.
any_message
A node and action to perform
Determines what should happen when contacts choose none of the options or enter text instead.
header_type
String
Type of headline shown above the message. Can be textimagevideo or document – or left out if you need no headline.
header_text
String
Required for header_type text. Represents the headline text, <= 60 chars.
header_url
String
Required for all non text header_types. Should be a link to the media file.
footer
String
Optional footer shown below the message, <= 60 chars.
options
option
options should be a sequence of maps, each one under the key “option”, with <= 3 options. The sequence can contain: - action: Action that should be taken when the option is selected - label: Main text on the element used for selection, <= 20 chars
A simple example:
yaml
0: input: message: "This is a button template" type: button_template key: select fallback: "Please enter a number" header_type: "text" header_text: "Header" footer: "footer" body: "body" any_message: messages: - "That's not right, try again." action: next: 0 options: - option: label: "Option One" action: next: 1 - option: label: "Option Two" action: next: 2

Input node: API

The API input node allows you to fetch data from, or send data to, external systems by making HTTP requests. This allows for a variety of use cases, such as fetching the status of an order or a delivery given a corresponding ID.
You can use the same text expansion capabilities we learned about in the message node to parse the response from the API and display it to the user.
Parameter
Value
Description
message
string
A string containing the text you want to prompt the contact for input with.
api
request / responsewhen
api is a map containing the request and response objects.
As you can see, the API node only has two parameters at the top level. api itself takes three parameters that specify the request and response as well as what happens when the request fails or succeeds. This is described in the table below:
Parameter
Value
Description
request
url / method / headers / data
The data you want to use to make your request.
response
key
The variable the data received in the response should be saved to.
when
failure / success
Determines how to handle request failures and how to proceed after a successful request.
The following example demonstrates general use of the API node to retrieve data and display it to the user:
yaml
# Making a GET request and handling the resulting JSON response 1: input: message: "Looking it up!" api: request: url: "https://mydomain/api/users/5" # The URL that should be called method: "get" # The method to use data: values: {} response: # Define a variable the reponse is saved to key: result when: failure: # Define what should happen when the request is not successful messages: - "Something went wrong" action: next: 0 success: messages: - "{{#result}}Your name is {{name}}, you work for {{#company}}{{name}}{{/company}} and your number is {{phone}}{{/result}}." action: next: 2 # Assuming the request we are making in the above example returns the following JSON object: { "id": 7, "name": "Kurtis Weissnat", "username": "Elwyn.Skiles", "email": "Telly.Hoeger@billy.biz", "address": { "street": "Rex Trail", "suite": "Suite 280", "city": "Howemouth", "zipcode": "58804-1099", "geo": { "lat": "24.8918", "lng": "21.8984" } }, "phone": "210.067.6132", "website": "elvis.io", "company": { "name": "Johns Group", "catchPhrase": "Configurable multimedia task-force", "bs": "generate enterprise e-tailers" } # After a successful request the message output would look like this: "Your name is Kurtis Weissnat, you work for Johns Group and your number is 210.067.6132."
The received JSON object is saved to the result variable. We can access the data at the top level of the object by expanding the keys by wrapping them in double curly braces. The same applies to accessing the data inside the company object. To signal that {{name}} in the second instance should refer to the name of the company and not to the name of the person, you can use a section by surrounding it with {{#company}}{{/company}} where appropriate.
💡
The above syntax is based on the Mustache templating engine. Click here to read more about the syntax.
The API node also supports making POST HTTP requests, which is demonstrated below:
yaml
1: input: message: "Sending data" api: request: url: "https://your-url/endpoint/{{tracking_id}}" method: "post" headers: # Define the headers of the request as key-value pairs User-Agent: 'Userlike Bot' Authorization: 'xxx-xxx-xxx-xxx' data: # Data is the request body of the POST request values: # Provide key-value pairs of data you want to send in the request body job: "Engineer" visits: 25 context: # Include data from the session context by providing the key you've saved it to - tracking_id response: key: result when: failure: messages: - "Something went wrong" action: next: 0 success: messages: - "Thank you for your submission." action: next: 2

Commands & actions

We‘ve already seen in the previous examples that every step ends with an action. Until now, we‘ve only used actions to proceed to the next step in the conversation flow by using the next command. UBL offers several more commands you can use in order to set or clear data of your contact, to navigate, or to forward the contact to human operators.

Commands

Command
Value
Description
set_name
string
Called on the contact, sets the name to the value provided.
set_email
string
Called on the contact, sets the email to the value provided.
set_mobile_number
string
Called on the contact, sets the mobile number to the value provided. The phone number must match the international phone number format E.164 in order to be persisted on the contact.
set_external_customer_id
string
Called on the contact, sets the external customer id to the value provided.
set_custom_field
object
Called on the contact or conversation, sets the custom field to the value provided. Also refer to our custom field documentation and the Examples below.
clear_name
boolean
Called on the contact. If true, clears the name currently saved on the contact.
clear_email
boolean
Called on the contact. If true, clears the email currently saved on the contact.
clear_mobile_number
boolean
Called on the contact. If true, clears the mobile number currently saved on the contact.
clear_external_customer_id
boolean
Called on the contact. If true, clears the external customer id currently saved on the contact.
clear_custom_field
object
Called on the contact or conversation. Clears the value of the given custom field id. Examples.
forward_group
string
Provide the operator group name you want to forward to as a string. You can additionally define a fallback behaviour if the group is not online.
forward_any
boolean
If true, forwards the conversation to any available operator. You can additionally define a fallback behavior for when no operator is available.
forward_skills
List of strings
Provide (by name) a list of skills an operator needs to possess to be eligible for this forward action. You can additionally define a fallbackbehaviour if no matching operator is available.
navigate
url
Provide a URL to navigate to as a string. The text for the navigation event can be set by using the text command. Define the fallback display by using setting the fallback value. Note that the target URL must have the same host as the URL the contact is currently visiting.
note_create
string
Called on the contact or the conversation. Creates notes during the current conversation. In the context of contact, the note will appear in the contact’s details. In the context of the current conversation, the note will appear after the latest message in the conversation’s message history.
subject
string
Called on the conversation. Sets the given text as the conversation’s subject. Set to null to reset the subject. Example.
topics
List of strings
Called on the conversation. Provide (by topic name) a list of topics to be set to the conversation. Set to null to clear the topics. Example.
locale
string
Called on the conversation. Set the conversation and contact language to one of: bg_BG, cs_CZ, da_DK, de_DE, en_US, el_GR, et_EE, fi_FI, fr_FR, hu_HU, it_IT, lt_LT, lv_LV, nl_NL, nb_NO, pl_PL, pt_BR, ru_RU, ro_RO, es_ES, sk_SK, sl_SI, sv_SE, tr_TR, zh_CN Example.
email_contact
boolean
Sends the transcript to the contact email after the conversation has ended. Example.
email_operator
list
Sends the transcript to a given list of operator emails after the conversation has ended. Example.
addon_dispatch
string
Sends the conversation to the defined and configured add-on in your organization when the conversation has ended. Example. Possible values - api - capsulecrm - centralstationcrm - emailticket - freshdesk - github - helpscout - hubspot - jira - lime - limego - mailchimp - onecrm - pipedrive - pipelinedeals - salesforce - slack - trello - zendesk

Examples

yaml
# Setting and clearing contact name: 0: messages: - "I need some information." input: message: "What's your name?" type: text key: name optional: false when: valid: action: contact: # If the input is valid, save the name to the contact set_name: "{{name}}" next: 1 exists: where: contact action: next: 1 1: input: message: "Is the name {{name}} correct?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 1 options: - option: "Yes" action: next: 2 - option: "No" action: contact: # Clear the contact name and ask again clear_name: True next: 1 2: messages: - "Nice to meet you, {{name}}" action: end: true # Forwarding to operators 0: input: message: "How may I help?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 0 options: - option: "I have a technical issue" messages: - "I see, let me forward you to our Technical Support department" action: forward_group: "Technical Support Group" - option: "I have questions about your pricing" messages: - "I'll forward your inquiry to our Sales team" action: forward_group: "Sales Group" - option: "I just want to speak to an agent" messages: - "I'll forward you to the next available operator" action: forward_any: true - option: "I have no further questions" messages: - "Have a nice day!" action: end: true # Forwarding to operators with fallback 0: input: message: "How may I help?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 0 options: - option: "I have a technical issue" messages: - "I see, let me forward you to our Technical Support department" action: forward_group: "Technical Support Group" fallback: messages: - "Nope, its not possible" action: next: 0 - option: "I have no further questions" messages: - "Have a nice day!" action: end: true # Using the navigate command: 0: messages: - "Navigating" action: navigate: "https://www.userlike.com" fallback: "Click here {{link}}" text: "Go to Userlike.com" # Using fallback in contact update 0: input: message: "Whats your mobile number?" type: regex format: "\\+49[0-9]{3,5}[0-9]{7,10}" key: mobile_number optional: false when: not-valid: messages: - "The format is not valid, please use +4917212345678" - "Let's try again.." action: next: 0 valid: action: contact: set_mobile_number: "{{mobile_number}}" fallback: messages: - "Nope, its not possible" action: next: 0 next: 1 exists: where: contact action: next: 1 1: input: message: "Is the mobile {{mobile_number}} correct?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 1 options: - option: "Yes" action: next: 2 - option: "No" action: contact: clear_mobile_number: True next: 0 # Creating a note for a contact 0: input: message: "To process your request, I need the order number." type: text key: order_number optional: false when: valid: action: contact: # Create a note within the contact’s context note_create: "Contact was unsatisfied with items ordered in {{order_number}}." next: 1 exists: where: contact action: next: 1 # Creating a note for the current conversation 0: input: message: "To process your request, I need the order number." type: text key: order_number optional: false when: valid: action: conversation: # Create a note within the conversation’s context note_create: "Customer requested a refund for the order {{order_number}}." next: 1 exists: where: contact action: next: 1
yaml
# Setting and clearing custom field 0: messages: - "What is your favorite fruit?" input: type: text key: "c35f82ba-6035-4217-8a48-95af996f64ce" optional: false when: valid: action: contact: set_custom_field: field_uid: "c35f82ba-6035-4217-8a48-95af996f64ce" field_value: "{{c35f82ba-6035-4217-8a48-95af996f64ce}}" next: 1 exists: where: contact action: next: 1 1: input: message: "{{c35f82ba-6035-4217-8a48-95af996f64ce}} is your favorite fruit?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 1 options: - option: "Yes" action: next: 2 - option: "No" action: contact: # Clear the custom field and ask again clear_custom_field: field_uid: "c35f82ba-6035-4217-8a48-95af996f64ce" next: 1 # Setting and clearing select custom field for contact or conversation 0: input: message: "What is your favorite color?" type: bubbles fallback: "Please enter a number" options: - option: "White" action: contact: set_custom_field: field_uid: "ec14f3efdeea46b6bb5960bc6b6db814" # adds the specified option ids field_value. field_value: "00476983-b1a3-4d10-93a6-e1280c2384ee" next: 1 - option: "Red" action: contact: set_custom_field: field_uid: "ec14f3efdeea46b6bb5960bc6b6db814" field_value: "f00faba0-5952-4184-866f-8ecf3f85a3a8" next: 1 - option: "Blue" action: contact: set_custom_field: field_uid: "ec14f3efdeea46b6bb5960bc6b6db814" field_value: "87c94069-8ae8-443a-b4eb-8e70b37ba2ea" next: 1 1: input: message: "Great choice or do you like to change your mind?" type: bubbles fallback: "Please enter a number" options: - option: "No" action: next: 2 - option: "Yes" action: contact: clear_custom_field: field_uid: "ec14f3efdeea46b6bb5960bc6b6db814" next: 0 # Setting and clearing multi-select custom field 0: input: message: "Which drinks do you like?" type: bubbles fallback: "Please enter a number" options: - option: "Water & Tea" action: conversation: set_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" # adds the specified option ids field_value. # field_value must be a list. field_value: - "d8d356e0-c88c-42cd-b086-55df92fcff41" - "e83d9127-acdb-4b33-b787-b72414149db8" next: 1 - option: "Juice" action: conversation: set_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" field_value: # multi-select value must be a list - "5c4f8cac-5c90-4830-8db9-d5d7b0831a49" next: 1 - option: "Coffee" action: conversation: set_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" field_value: - "6d778d2c-edcf-4088-a227-df9549ffcb08" next: 1 - option: "Skip" action: next: 2 1: input: message: "Which drink you like to remove?" type: bubbles fallback: "Please enter a number" options: - option: "Water" action: contact: clear_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" # removes the specified option uids # given in `field_value`. # multi-select field_value must be a list field_value: - "d8d356e0-c88c-42cd-b086-55df92fcff41" next: 20 - option: "Tea" action: contact: clear_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" field_value: - "e83d9127-acdb-4b33-b787-b72414149db8" next: 20 - option: "Juice" action: contact: clear_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" field_value: - "5c4f8cac-5c90-4830-8db9-d5d7b0831a49" next: 20 - option: "Coffee" action: contact: clear_custom_field: field_uid: "64cb6bb763f44f86909ecfe79762ae56" field_value: - "6d778d2c-edcf-4088-a227-df9549ffcb08" next: 20 - option: "Skip" action: next: 20
yaml
# Set and clear conversation subject 0: messages: - "Setting the subject" action: conversation: subject: "Chat of customer {{customer_id}}" next: 1 1: messages: - "Clearing now the subject again" action: conversation: subject: null next: 2
yaml
# Set and clear conversation topics 0: messages: - "Set topics" action: conversation: topics: - Support - Lead next: 1 1: messages: - "Lets clear topics" action: conversation: topics: null next: 2
yaml
# Set conversation and contact locale. 0: action: conversation: locale: "de_DE" next: 1
yaml
# Sending the transcript to the contact after the conversation ended 0: input: message: "What is your email address?" type: text key: email optional: false when: valid: action: contact: # update the contact's email address set_email: "{{email}}." next: 1 exists: where: contact action: next: 1 1: messages: - Thank you for providing us your email. - We'll send you the transcript after our conversation has ended action: email_contact: true # Sending the transcript to a list of operators 0: messages: - I will escalate your issue to my colleagues. action: email_operator: - operator1@testuslk.de - operator2@testuslk.de # Dispatch the conversation to an add-on 0: messages: - Thank you for reaching out to us! - Hope to talk to you soon again. action: addon_dispatch: helpscout

Session context

The session can contain information which you can use in your UBL script by saving it to variables, as we've previously seen.
Conversely, you can also access session information in your UBL scripts in case it's already been provided by the contact, for example when using the mandatory registration mode.
If we want to access the contact's name in order to give them a personal greeting (assuming you've gathered it from the registration form before the chat), we would simply use an input step and perform an 'exists' check for the contact name. Since this information was required to start the session, it will be available to the bot. Refer to the "THE EXISTS LOGIC" section above for an example.
You can also access data not saved to the contact during the same session by referring to the variable it was saved to. If you previously asked the contact for their customer number, you will be able to reference the variable this was saved to in a later step in order to make an API call, for example.

Examples

We've prepared an example below that you can use as a starting point for your own scripts.
The following script puts together some of the elements we've seen previously to gather a contact's data before trying to direct them towards certain information.
yaml
--- config: abort: keywords: - stop skip: keywords: - skip global_nodes: offer_help: keywords: - help me! - help - ask for help input: message: "How can i help you?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 0 options: - option: "Questions about the product" messages: - "Ok, i will forward you to our Support department" action: forward_group: "Support" - option: "I have no further questions" messages: - "Have a nice day" action: end: true forward_operator: keywords: - operator - agent - questions about the product - human messages: - Alright! I will try to forward you to an operator. action: forward_any: true 0: messages: - "Welcome to our chat!" - "I'm happy to assist you." action: next: 1 1: messages: - "I need some information about you first." input: message: "What's your name?" type: text key: name optional: false when: valid: action: contact: set_name: "{{name}}" next: 2 exists: where: contact action: next: 2 2: input: message: "Is the name {{name}} correct?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 2 options: - option: "Yes" action: next: 3 - option: "No" action: contact: clear_name: True next: 1 3: messages: - "Nice to meet you, {{name}}" action: next: 4 4: input: message: "What's your email address?" type: email key: email optional: true when: not-valid: messages: - "This doesn't seem to be a valid email address." - "Let's try again!" action: next: 4 valid: action: contact: set_email: "{{email}}" next: 5 skip: action: next: 6 exists: where: contact action: next: 5 5: input: message: "Is the email {{email}} correct?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 5 options: - option: "Yes" action: next: 6 - option: "No" action: contact: clear_email: True next: 4 6: input: message: "Hello {{name}}! How may I help?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 6 options: - option: "I have questions about your product." messages: - "I'll forward you to our Sales department." - "They will happily answer any questions you might have!" action: forward_group: "Sales" - option: "I have questions about the integration on my website." action: next: 7 - option: "I have no further questions" messages: - "Have a nice day" action: end: true 7: input: message: "Which website integration are you interested in?" type: carousel key: select fallback: "Please enter a number" any_message: action: next: 7 options: - option: media: "https://d3upe020n1uosc.cloudfront.net/static/web/images/tutorial_logo_shopware.png" headline: "Shopware" subheadline: "Shopware is the ideal solution for meeting the changing demands of ecommerce, giving you the freedom to quickly and easily leverage your growth potential" action: navigate: "https://www.userlike.com/en/public/tutorial/um/website/shopware" fallback: "Click here {{link}}" text: "Go to the Shopware integration" next: 8 - option: media: "https://d3upe020n1uosc.cloudfront.net/static/web/images/tutorial_logo_squarespace.png" headline: "Squarespace" subheadline: "Create a website with an award-winning template. Get your unique domain today. No Plugins Necessary." action: navigate: "https://www.userlike.com/en/public/tutorial/um/website/squarespace" fallback: "Click here {{link}}" text: "Go to the Squarespace integration" next: 8 - option: media: "https://d3upe020n1uosc.cloudfront.net/static/web/images/tutorial_logo_plain_website.png" headline: "HTML" subheadline: "Paste the code into the bottom of your website" action: navigate: "https://www.userlike.com/en/public/tutorial/um/website/plain" fallback: "Click here {{link}}" text: "Go the the HTML website integration" next: 8 - option: headline: "None of these" subheadline: "Go back to the previous step" media: "https://d3upe020n1uosc.cloudfront.net/static/web/svg/icon_support_help.svg" action: next: 6 8: input: message: "Did this answer your question?" type: bubbles key: select fallback: "Please enter a number" any_message: action: next: 8 options: - option: "Yes" action: next: 9 - option: "No" action: next: 6 9: messages: - "Glad I could help!" - "Have a great day!" action: end: true
Depending on whether your bot answers all conversations or only the ones coming in while you are offline, you can adjust your conversation flow to gather the information that's important to you or present your contacts with useful resources to help them out right away.