Quickstart

Follow these steps to have a basic integration of the app's miles® SDK on your website.

Web Quickstart

Conditions and minimum requirements

Supported on all browsers except IE9 and below.

Desktop:

Browser

Chrome

Edge

Firefox

IE

Opera

Safari

Oldest version supported

5

all

4

9

10.5

5

Support coverage

100.00%

100.00%

99.37%

94.49%

100.00%

100.00%

Mobile:

Browser

Android WebView

Chrome

Edge

Firefox

Opera

Safari

Samsung Internet

Oldest version supported

all

all

all

4

all

all

all

Support coverage

100.00%

100.00%

100.00%

99.37%

100.00%

100.00%

100.00%

Stats calculated based on data on gs.statcounter.com from December 2018

100% compatibility is possible, but implies adding quite a few additional polyfills. We opted for a leaner SDK instead of supporting old and mostly unused browser versions. Our SDK weighs around 500kb.

Overview

After following the instructions below, your html will look approximately like this:

<html>
<head>
...
<link rel="stylesheet" type="text/css" href="path/to/appsmiles-sdk.css" />
<link rel="stylesheet" type="text/css" href="path/to/appsmiles-icons.css" />
...
</head>
<body>
...
<div id="apm-sticker"></div>
...
...
<script>
var apmConfig = {...};
var apmTranslations = {...};
</script>
<!-- or <script src="path/to/apm-config.js"></script> -->
<!-- or <script src="path/to/apm-translations.js"></script> -->
<script src="path/to/appsmiles-sdk.js"></script>
...
</body>
</html>

Vocabulary

I. Installation

We generally create a release personalized for your needs. Contact us to get the SDK files.

In order for everything to work properly, we require that the folder we provide be integrated as-is. Do not move the files inside, or some paths will be broken.

II. Configuration

There are 5 different HTML tags to add to your html for the SDK. They must be put in the following order:

1. Style

Two files:

  • appsmiles-sdk.css

  • appsmiles-icons.css

The SDK comes with it's own stylesheet (1st file) and icon font (2nd file). All of the class and ids are prefixed with apm- in order to prevent interference in the global scope.

<head>
...
<link rel="stylesheet" type="text/css" href="path/to/appsmiles-sdk.css" />
<link rel="stylesheet" type="text/css" href="path/to/appsmiles-icons.css" />
</head>

Don't hesitate to contact us if you would like style changes

If instead you see squares instead of icons, this means that appsmiles-icons.css wasn't properly loaded. Check that the tag is present, and that the file is loaded before appsmiles-sdk.js . Same thing if you see raw text appearing with no style (temporarily, or permanently) where the sticker is supposed to be. This can often happen when files are loaded asynchronously, in which case you have to load these files synchronously in respect to each other (see Ajax and other asynchronous integrations).

(left) No icons (right) No SDK CSS

2. Configuration (apmConfig)

There are many configuration options, some required and others optionals. There are also configuration to help during the development process.

You can externalize this variable into its own JS file, as long as it is called before the main JS file

var apmConfig = {
// Required
apiBaseUrl: "[Required] {string} URL of the appsmiles API, modify to point to sandbox or prod environment",
clientSignature: "[Required] {string} Signature created with HmacSHA256(timestampString, partnerSecretString).toString().substring(0, 15).toUpperCase();",
clientSignatureTimestamp: "[Required] {number} Timestamp used for client signature creation",
defaultSticker: "[Required] {string} Absolute or relative url of the image to use for the default sticker",
lang: "[Required] {string} Language in which the SDK should be. 2 letter country code.",
openFrom: "[Required] {string} Direction from which the SDK should open (N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, C)",
partnerId: "[Required] {string} ID of the partner in the appsmiles back-office",
closeIconPosition: "[Required] {string} Position of the close icon. Same values than openFrom. Keep empty field (default) to hide.",
tabs: "[Required] {ComplexType} Configure the number of tabs and which screen they lead to",
ribbonDirection: "[Required] {string} Direction towards which the notification ribbon should extend (N, E, S, W)",
// Conditional (scenario specific)
showBalanceInSticker: "[Conditional] {boolean} Whether to show the user's balance in the sticker",
// Optional
loginPageUrl: "[Optional] {string} Url of the sign-in/sign-up page",
onClickSticker: "[Optional] {string} Url to navigate to instead of opening the modal",
hideStickerIfOptOut: "[Optional] {boolean} Hide sticker if user chooses to opt out. Default is false. Consider to integrate a way for the user to opt back in if you choose to set it to true",
hideStickerIfSdkOff: "[Optional] {boolean} Hide sticker if SDK is set to OFF or if non-functional. Default is false",
timeoutDuration: "[Optional] {number} Number of seconds to wait before http requests enter timeout",
notificationDuration: "[Optional] {number} Duration in ms of the notification (including animation)",
generosityBufferPolicy: "[Optional] {number} Policy as to how to handle triggerActions when user is not connected. -1: always discard, -2: keep after userClientConnect is called (while waiting for server response or RGPD opt-in), 0: always keep, x > 0: keep only actions in the last x seconds after user connected.",
stickerNotificationBadgePolicy: "[Optional] {number} Policy as to when to show the notification badge on the sticker. -1: never show, 0: always show, 1: show when new content available"
templates: "[Optional] {ComplexType} Specify which template to use for a given screen",
notifications: "[Optional] {ComplexType} Specify a template, a resource key and an apm deeplink per notification type",
// Development
enableLogs: "[Dev] {boolean} Enable logs, overrides the appsmiles debugMode setting",
logLevel: "[Dev] {string} Set log level (verbose, debug, info, warn, error)",
forceRefresh: "[Dev] {boolean} Bypass the waiting time (default: 5 minutes) between API checks on page reload",
forceDeeplink: "[Dev] {string} Force the deeplink button to appear and to redirect to link in variable",
}
// Example for complex types
var apmConfig = {
templates: {
gifts: "gifts" (default) | "gifts--cover",
gift: "gift" (default) | "gift--cover",
burns: "burns" (default) | "burns--cover",
burn: "burn" (default) | "burn--cover"
},
notifications: {
global: {
template: "notif" (default) | "notif--fullscreen",
foregroundGraphicResourceKey: "${resourceKey}", (default: undefined)
onClick: "apm://default" (default) | "${apmDeeplink}"
},
trophy | generosity | earn | gift | challenge | trophy | level: {
...
}
},
tabs: [
{ onClick: "apm://gamification-challenges" | "${apmDeeplink}" },
...
]
}

2.1. Generating the clientSignature(required)

Among the required options in apmConfig, there is the clientSignature. You will find below what you need to know to generate this signature.

In order to enforce a higher degree of security, our SDK uses JSON Web Tokens (JWT) to encrypt requests sent to our server. To do that, we need a signature. However, since Javascript code is completely visible to the client, the signature must be generated by your server.

This signature must be generated server-side, in the language your server uses (e.g. PHP, Ruby). It must not be calculated client-side (browser).

Signature type: HMAC SHA-256. Arguments: timestamp (current time) and the partnerSecret key that we will have provided to you. Post-processing: Keep first 15 characters and convert to uppercase.

JS
PHP
JS
HmacSHA256( // using CryptoJS library
timestamp: string, // ! Very important for it to be a STRING
partnerSecret: string)
.toString()
.substring(0, 15)
.toUpperCase();
PHP
<?php
$partnerSecret = <PARTNER_SECRET>;
$clientSignatureTimestamp = (new DateTime())->getTimestamp();
$rawClientSignature = hash_hmac('sha256', $clientSignatureTimestamp, $partnerSecret);
$clientSignature = strtoupper(substr($rawClientSignature, 0, 15));
// TODO: make $clientSignatureTimestamp and $clientSignature available to the client

The signature must be regenerated on each page load. The timestamp is only valid 10 minutes.

Now on the client side, you add clientSignature and clientSignatureTimestamp in the apmConfig object:

<script>
apmConfig.clientSignature = <clientSignature>;
apmConfig.clientSignatureTimestamp = <clientSignatureTimestamp>;
</script>

3. Translations (apmTranslations)

Our SDK comes with a default French translation. If you wish to change it, or add more languages, you can use the global variable apmTranslations so that the SDK can access them, and use apmConfig.lang to point to the correct translation.

See the default translations.js file provided.

<script src="path/to/apm-translations.js"></script>

If keys are missing, error logs will be printed in the browser's console, indicating which ones are missing.

4. The SDK

This is the main JS file, containing the logic, and UI elements (except the styling).

<script src="path/to/appsmiles-sdk.js"></script>

5. HTML anchor

The SDK will look for a div with the id 'apm-sticker' like so : <div id="apm-sticker"></div>. Place this anchor where you wish the button to appear.

The design of the sticker, the placement of the modal and the direction of the notifications are all configured in the style file.

III. Initialization

The SDK initializes itself automatically when the 4. The SDK script tag is executed.

Hurray !

Ajax and other asynchronous integrations

If you are not loading through HTML tags, make sure that the order is respected. The most important is that the stylesheets, font, config and translations are fully loaded before appsmiles-sdk.js is loaded.

If the order is not respected, you may see:

  • A bunch of text appearing where the sticker is supposed to be (CSS was not loaded in time)

  • Font icons not appearing (font or font css not loaded in time)

  • Console errors about apmConfig

  • Text inside the SDK and icons don't match what you configured (default translation is loaded because custom one wasn't loaded in time)

Here is a very basic example of asynchronous loading in one of the correct order:

appsmiles-icons.css > appsmiles-sdk.css > apm-config.js > apm-translations.js > appsmiles-sdk.js

var loadApm = function () {
var cssIcons = document.createElement('link');
cssIcons.rel = "stylesheet";
cssIcons.type = "text/css";
cssIcons.href = "./appsmiles-icons.css";
cssIcons.onload = function () {
var cssSdk = document.createElement('link');
cssSdk.rel = "stylesheet";
cssSdk.type = "text/css";
cssSdk.href = "./appsmiles-sdk.css";
cssSdk.onload = function () {
var scriptConfig = document.createElement('script');
scriptConfig.src = "./apm-config.js";
scriptConfig.onload = function () {
window['apmConfig'].clientSignature = createClientSignature();
var scriptTrans = document.createElement('script');
scriptTrans.src = "./apm-translations.js";
scriptTrans.onload = function () {
var scriptSdk = document.createElement('script');
scriptSdk.src = "./appsmiles-sdk.js";
document.head.appendChild(scriptSdk);
}
document.head.appendChild(scriptTrans);
}
document.head.appendChild(scriptConfig);
}
document.head.appendChild(cssSdk);
}
document.head.appendChild(cssIcons);
}
loadApm();