Custom App
In this section you'll find the technical documentation for creating a Custom App that will be accessible from the agents' (and Ibbü experts', where applicable) desk.
Custom App extends the capabilities of the Desk by allowing our clients to embed their own apps in a dedicated panel.
General guidelines
A complete breakdown of our guidelines for Custom Apps can be found in our knowledge base.
App development
The apps that can be embedded in the Desk are web apps coded in any web compliant technology - static web page, dynamic web pages such as php or jsp generated, single page applications written in Angular or React, etc...
These apps will be embedded in an iframe
element in the Desk, and the web server serving these apps must allow them to run in an iframe on the iAdvize domains: https://sd.iadvize.com or https://ha.iadvize.com. This is done by configuring the X-FRAME-OPTIONS
header.
The app can communicate with the desk by using a library provided by iAdvize.
Please note that one iframe is created per conversation in order to keep a context for an app for each conversation. It is recommended to keep the app very lightweight and avoid heavy processing or streaming updates.
Library quick start
To use the library an app must include a javascript bundle in the html with the following code.
<script src="https://static.iadvize.com/conversation-panel-app-lib/2.9.0/idzcpa.umd.production.min.js"></script>
Then in the javascript code of the app the library can be used as follows.
window.idzCpa.init().then(client => {
client.insertTextInComposeBox('Hello world!');
});
⚠️ CPAs available on the iAdvize iOS and Android apps must use the version 2.0.3 or greater.
API reference
idzCpa
idzCpa
is a global variable used as the entry point of the CPA library.
init
function init(): Promise
The client is obtained via the idzCpa.init
function that returns a Promise.
const clientPromise = idzCpa.init();
clientPromise.then(client => { / do something /});
Client context
client.context // => Context
type Context = {
conversationId: string;
projectId: string;
channel: Channel;
language: string;
}
// list of available channels:
enum Channel {
AppleBusinessChat = 'APPLE_BUSINESS_CHAT',
Call = 'CALL',
Chat = 'CHAT',
Facebook = 'FACEBOOK',
FacebookBusinessOnMessenger = 'FACEBOOK_BUSINESS_ON_MESSENGER',
MobileApp = 'MOBILE_APP',
Sms = 'SMS',
Video = 'VIDEO',
Whatsapp = 'WHATSAPP',
}
The context
property on the client returns the conversation context: conversation ID and project ID.
client.context.conversationId // => '5701a92f-a8e3-49ad-81dc-ac801171f799'
client.context.projectId // => '3103'
client.context.channel // => 'CHAT'
client.context.language // => 'fr'
List of commands available
insertTextInComposeBox
Allows the CPA to send some text to the active thread compose zone.
pushCardInConversationThread
Allows the CPA to send a card to the active conversation thread.
pushCardBundleInConversationThread
Allows the CPA to send a card carousel to the active conversation thread.
pushApplePayPaymentRequestInConversationThread
Allows the CPA to send an Apple Pay Payment request in the conversation thread.
getJWT
Allows the CPA to get a JWT token signed with the secret token defined in the connector of the CPA.
How to use each command
insertTextInComposeBox
Allows the CPA to send some text to the active thread compose zone.
Signature
function insertTextInComposeBox(value: string): void
⚠️ value field is required
Example
client.insertTextInComposeBox('Hello world!');
Result

pushCardInConversationThread
Allows the CPA to send a card to the active conversation thread.
Signature
type Action = {
type: 'LINK';
title: string;
url: string;
}
type Card = {
title?: string;
text?: string;
actions: Action[],
image?: {
url: string;
description: string;
}
}
function pushCardInConversationThread(value: Card): void
⚠️ actions field is required and must contain at least one action of LINK type ⚠️ title, text and image fields are optional
Example
const card: Card = {
title: "Card 1 title",
text: "Card 1 description",
actions: [
{
type: 'LINK',
title: "Click here",
url: "https://..."
},
],
image: {
url: "https://...",
description: "Image description add to alt img attribute",
}
}
client.pushCardInConversationThread(card)
Result

pushCardBundleInConversationThread
Allows the CPA to send a card carousel to the active conversation thread.
Signature
type Carousel = {
title?: string;
cards: Card[]; // See pushCardInConversationThread command for more information of Card type
}
function pushCardBundleInConversationThread(value: Carousel): void
⚠️ title field of Carousel is optional ⚠️ cards field of Carousel is required
Example
const card1: Card = {
title: "Card 1 title",
text: "Card 1 description",
actions: [
{
type: "LINK",
title: "Click here",
url: "https://...",
}
],
image: {
url: "https://...",
description: "Image description add to alt img attribute"
}
}
const card2: Card = {
title: "Card 2 title",
text: "Card 2 description",
actions: [
{
type: "LINK",
title: "Click here",
url: "https://...",
}
],
image: {
url: "https://...",
description: "Image description add to alt img attribute"
}
}
const carousel: Carousel = { cards: [ card1, card2 ] }
client.pushCardBundleInConversationThread(carousel)
Result

getJWT
Allows the CPA to get a secured JWT token. This JWT is signed with the secret token defined in the connector of the CPA.
Signature
function getJWT(): Promise
Example
// use jwtToken on CPA for secure request
client.getJWT().then((jwtToken: string) => { / use JWT token / })
pushApplePayPaymentRequestInConversationThread
Allows the CPA to send an Apple Pay Payment request to the active conversation thread.
The CPA can only send an Apple Pay Payment request to a conversation from an Apple channel.
Signature
type ApplePayPaymentRequestType = {
requestIdentifier: UUID;
payment: ApplePayPaymentRequest;
receivedMessage: ApplePayReceivedMessage;
}
// Detail for payment field type
type ApplePayPaymentRequest = {
currencyCode: string;
lineItems: PaymentItem[];
requiredBillingContactFields: ApplePayContactField[];
requiredShippingContactFields: ApplePayContactField[];
shippingMethods: ShippingMethod[];
total: PaymentItem;
}
type PaymentItem = {
amount: string;
label: string;
type: ApplePayLineItemType;
};
enum ApplePayLineItemType {
final,
pending,
}
type ShippingMethod = {
amount: string;
detail: string;
identifier: string;
label: string;
};
enum ApplePayContactField {
email = 'email',
name = 'name',
phone = 'phone',
postalAddress = 'postalAddress',
phoneticName = 'phoneticName',
}
// type for receivedMessage field
type ApplePayReceivedMessage = {
type: 'CARD';
data: CardType;
}
type CardType = {
title?: string;
text?: string;
image?: CardImage;
actions: LinkAction[];
};
type CardImage = {
url: string;
description: string;
};
type LinkAction = {
type: 'LINK';
title: string;
url: string;
};
// Error
type ActionError = {
message: string;
details?: string[];
}
function pushApplePayPaymentRequestInConversationThread(applePayPaymentRequest: ApplePayPaymentRequestType): Promise
Note
If the request of payment is not sent, you may have an error in your request payload. To help you fix your payload, you can catch the error Promise: an ActionError is available with more details on what's happening.
More details about the ApplePayPaymentRequest
type are provided in the official Apple developer documentation.
Example
const applePayPaymentRequest: ApplePayPaymentRequestType = {
requestIdentifier: "83f86edb-XXXXX", // UUID
payment: {
currencyCode: "USD",
lineItems: [
{
amount: "45",
label: "Earpods",
type: "final"
},
{
amount: "955",
label: "iPhone 12 mini",
type: "final"
}
],
requiredBillingContactFields: ["email"],
requiredShippingContactFields: ["email"],
shippingMethods: [
{
amount: "10",
detail: "Available within an hour",
identifier: "in_store_pickup",
label: "In-StorePickup"
}
],
total: {
amount: "1000",
label: "TOTAL",
type: "final"
}
},
receivedMessage: {
type: "CARD",
data: {
title: "Please check this payment request",
text: "Check this payment request and choose your shipping method",
actions: [],
style: "icon"
}
}
}
client.pushApplePayPaymentRequestInConversationThread(applePayPaymentRequest)
.then(() => /* success apple pay payment request */)
.catch((error: ActionError) =>
/* error.message -> Error on command request */
/* error.details (if exists) -> More details about the error if it exists */
)
Result
Message for an operator in the conversation thread when the CPA pushes an Apple Pay Payment Request:

Success payment:

Failed payment:

Style sheet
The library also provides a standalone stylesheet with CSS variables built-in to fit iAdvize's design guidelines.
An app can include it either in its HTML:
<link rel="stylesheet" src="https://static.iadvize.com/conversation-panel-app-lib/2.9.0/idzcpa.base.css">
Or as a top-level import inside a preprocessed-stylesheet:
@import 'https://static.iadvize.com/conversation-panel-app-lib/2.9.0/idzcpa.base.css';
A complete description of the provided variables can be found in our knowledge base.
Library Change log
1.0.0
Initial version with support for inserting text in the compose box via insertTextInComposeBox
.
1.2.0
Add Conversation Panel App style sheet.
2.0.3
Add mobile apps support - from this version apps hosted in the iAdvize iOS and Android apps can use this library.
2.1.0
Return the conversation context in the client.
2.3.1
Support for inserting image type card and carousel of image type cards in the conversation thread via insertCardInConversationThread
and insertCarouselInConversationThread
2.4.0
Replace command name and signature of each command: insertCardInConversationThread
is replaced by pushCardInConversationThread
and insertCarouselInConversationThread
is replaced by pushCardBundleInConversationThread
2.6.0
Add new action getJWT
to get a secured JWT token
2.7.0
Add new command pushApplePayPaymentRequestInConversationThread
to send Apple Pay Payement request in the conversation thread
2.9.0
Add channel on init context
Configuration
Under the Plugins section create a Conversation Panel App and then edit the following fields:
App name
This is the name that will show in the toolbar button that starts your app. The name must be provided as a json object that contains a default
name and then names for each language the app needs to support.
For instance {"default": "Orders", "EN": "Orders", "FR": "Commandes"}
.
Icon name
The icon name refers to a set of predefined icons provided by iAdvize that will appear in the button that starts the app.
A live preview of each icon can be found here
Here is the list of available options by domain - the name must be entered in upper case.
#Coupon
COUPON, DOLLAR, PERCENTAGE, TICKETS
#Qualify lead
STAMP
#Segmentation
TARGET, CARD
#Delivery
DELIVERY, PACKAGE
#Orders
ORDER, BOXES
#Stock
STOCK, WAREHOUSE
#Knowledge base
RECOMMENDATION, FILES, FOLDERS, SEARCH
#User account
PROFILE, TARGETING, PROFILECARDS
#Invoicing
INVOICING
#Payment
PAYMENT
#Shopping cart
SHOPPINGCART, SEARCHSHOPPINGCART
#Product availability
BAGQUESTION, BAGSEARCH, PACKAGESEARCH
#Stores
STORE
#Location
LOCATION, POSITION, LOCATIONPIN
#Assistance
TOOLS, TOOLING, HELP
#Note
NOTE
#Booking
BOOKING
#Tags
TAG
#Hotels & Services
HOTELS, HOTELOFFER, SERVICES
#Generic/Random
NOTEBOOK, DIAMOND, BOUSSOLE, SHIRT, GEAR, FRAME45, TARGETING

iFrame URL
This field provides the URL that the Desk will use to start your app. It must be a public URL that can be targeted by the browser that runs the desk and available via https.
For instance: https://mycompany.com/ordersapp
Enable for operators
Check this checkbox to make the app available for operators.
Enable for experts
Check this checkbox to make the app available for ibbü experts.
Use authentication
Check this checkbox if your app requires a proof that the CPA is loaded within the desk or if you want the ID of the operator. You will receive a JWT in the url parameters that is signed with the secret token defined in the connector of the CPA. For instance a URL with a JWT will look like this:
https://app.iadvize.com/order.html?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
The JWT can be decoded and validated by standard JWT libraries, for instance the jsonwebtoken library from auth0 https://github.com/auth0/node-jsonwebtoken
The code to decode a JWT looks like this:
const inputToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";
const secrettoken = '97db6bc85144af406a0e0040ad6f354b';
try {
const verifiedToken = jwt.verify( inputToken, secretToken, { algorithms: ['HS256'] });// do something with verifiedToken// example token// {// iss: 'iadvize',// sub: '270586',// aud: 'https://app.iadvize.com/order.html',// exp: 1644502986,// iat: 1644502926,// email: '[email protected]'// }
} catch(err) {
// handle the error by returning an unauthorised response
}
The JWT contains the following properties:
iss
the issuer is alwaysiadvize
sub
the subject, it is the operator IDaud
the audience is the url of the targeted CPAiat
the issue time, unix timestamp in number of secondsexp
the expiry time, unix timestamp in number of secondsemail
the operator email address
Last updated
Was this helpful?