The SDK comes with it's own stylesheet (1st line) and icon font (2nd line). All of the class and ids are prefixed with apm- in order to prevent interference in the global scope.
Don't hesitate to contact us for style changes you would like to do.
If you wish to change the style yourself, read the instructions below:
SCSS methodologies
Our CSS is compiled from SCSS and is organized through the use of two methodologies: ITCSS and BEM.
ITCSS Architecture. This allows to have a clearer hierarchy and css priority (the lower the CSS is, the higher its priority) and is useful to prevent the use of !important. It consists in organizing the files in the following order:
1-settings
2-tools
3-generic
4-elements
5-objects
6-components
7-themes
8-utilities (Trumps)
CSS class names follow the naming convention of BEM (Block__Element--Modifier). This convention may seem obscure at the beginning, but it allows for consistent class names.
.apm-page__button--state-success
.apm-page: Block
__button: Element
--state-success: Modifier
Each HTML element will often have a general class name (shared by multiple elements on different pages) and a unique class (so that we can modify the style of this element only). This allows for both refactoring and detail work.
apm-media__image is a general class name and apm-gift__image is the unique class.
SCSS variables
Our SCSS was written in a way so that the SDK can be customized by duplicating and modifying the file 1-settings/s-base.scss. This file is a mastersheet of SCSS variables which are used in all of the other SCSS files. It is thus possible to change the look and feel of the SDK only by modifying this file. It is always possible to do fine-grain work by editing the SCSS lower in the hierarchy.
These SCSS variables also follow the BEM naming convention. This is an example of how SCSS variables are organized in 1-settings/s-base.scss:
Generic variables (located on top, reused by variables below within s-base.scss).
This hierarchy in the variables creates a cascade of reference, but allows to modify multiple elements related to each other, by changing just one variable.
Examples
$font-family--header will change the font for all headers
$color--primary, since it is used by other SCSS variables or by the style directly, will modify button colors, the tab background colors, etc ...
2. Configuration (apmConfig)
In order for the SDK to work properly, you will need to add the following Javascript variable before loading it.
It is possible to externalize this variable into it's own JS file, as long as it is called before the SDK.
<script>
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.",
mediaBaseUrl: "[Required] {string} URL of the appsmiles media folder, modify to point to sandbox or prod environment",
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",
ribbonDirection: "[Required] {string} Direction towards which the notification ribbon should extend (N, E, S, W)",
closeIconPosition: "[Required] {string} Position of the close icon. Same values than openFrom. Keep empty field (default) to hide."
// Conditional (scenario specific)
partnerClientId: "[Conditional] {string} ID of the user according to the integrator's database",
segments: "[Conditional] {JSON} JSON of the user's segment",
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",
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"
// Development
openAndLoad: "[Dev] {string} Have modal open on a specific screen on refresh (welcome, challenge, menu, gifts, gift, burns, burn, earns, levels, pages-mentions, pages-onboarding-anonymous, pages-onboarding-connected)",
overrideProgTTL: "[Dev] {number} Override progTTL (automatic refresh interval), in seconds",
alwaysNewAction: "[Dev] {boolean} Always get a new action to suggest to the user (otherwise, only new action if user completed the current one)",
clearApmCacheOnRefresh: "[Dev] {boolean} Clear localStorage and sessionStorage for any apm keys",
resetOptInOnRefresh: "[Dev] {boolean} Reset opt in on refresh to see onboarding with buttons everytime",
enableLogs: "[Dev] {boolean} Enable logs, overrides the appsmiles debugMode setting",
logLevel: "[Dev] {string} Set log level (verbose, debug, info, warn, error)",
forceCookies: "[Dev] {boolean} NOT IMPLEMENTED YET. Force use of cookies instead of WebStorage (if SDK should appear across sub domains)",
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",
}
</script>
How to generate clientSignature
In order to enforce a higher degree of security. Our SDK uses JSON Web Tokens (JWT) to encrypt requests sent to our server.
In order to do this, 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, AngularJS, Ruby).
You then add the generated string in the apmConfig.clientSignature object
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.
Javascript example:
HmacSHA256( // using CryptoJS library timestamp: string,// ! Very important for it to be a STRING partnerSecret: string).toString().substring(0,15).toUpperCase();
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.
Note: If keys are missing, error logs will be printed in the browser's console, indicating which ones are missing.
4. The SDK
Insert the link to the SDK that we have provided to you here.
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.
Be sure to configure $modal--open-direction and $notif-direction in the SCSS to match the anchor's placement.
6. The SDK methods (apmApi)
If all of the above was configured properly, you should now see the SDK sticker and have access to the global variable apmApi.
userClientConnect
Connects the user.
Should be called right after you've logged in/registered a user.
Do not call this method on each page. The SDK keeps the user connected to appsmiles across webpages through the use of localStorage.
apmApi.userClientConnect( email: string, partnerClientId: string, firstName: string, lastName: string, segments: JSON// e.g. {"a": "0", "b": "c"} // Note: for `segments`, you MUST use double quotes, // single quotes are invalid JSON characters in PHP // (language which our API uses) dataConsentCode?:-1|0|1// NOT_SET = -1, ACCEPT = 0, REFUSE = 1// Optional parameter that allows to set directly RGPD consent)
Return value
Error
If invalid arguments
If already connected
If user has not accepted RGPD yet (will connect once it is)
userObject
{user: userObject}
Example
Connecting user John Doe with his email 'john.doe@mail.com' associated with the ID/token you gave him. The segments here must match with the definition appsmiles has, in this example case: {s = sexe: m = male, p = prime: 0 = false}
Connecting user John Doe with his email 'john.doe@mail.com' associated with the ID/token you gave him. The segments here must match with the definition appsmiles has, in this example case: {s = sexe: m = male, p = prime: 0 = false}
Warning: This method is specific to certain scenarios. Contact us to know if you should use it.
Creates a user and rewards him with the given actions (validated by the appsmiles server). Note 1: Does not connect the user. Note 2: If user already exists, assigns the actions (does not create duplicate).
If the action uses 'rules and filters', you have to add the properties object in each action with the corresponding properties.
apmApi.createUserWithActions( actions: Array<{tagID: string, properties?: {[code: string]: string}}>,// array of objects with the property 'tagID' email: string, partnerClientId: string, firstName: string, lastName: string, segments: any)
Return value
Error (see error message)
earnObject (last earn in list) and userObject
{earn: earnObject,user: userObject}
Example
var actions = [ {tagID:"tag1"}, {tagID:"tag2"}, {tagID:"tag3"},];apmApi.createUserWithActions(actions,"sdkweb@appsmiles.fr","987654321","John","Doe",undefined);
Only necessary when using our filter functionality.
Call these methods to update user properties. These user properties are stored permanently on a device (using localStorage). The keys and values must match with the filters established with appsmiles.
Tells our server that the user accomplished the given action after the SDK checks whether the user is allowed to do the action (frequency, filters, etc...).
The tags must match with the tagging plan established with appsmiles.
/** * Tells the appsmiles server that the user accomplished an action (trigger) * which awards points if the conditions are met. * DYNAMIC TAGS: you can have the tagId in its dynamic form * (e.g. display_product#$#display_product#$#categoryId=12#$#productId=387) * * @param{string} tagId * @param{{[s: string]: string}} properties Optional, both keys and values MUST BE strings * @returns * { * generosityValue: "5", * userBalance: "340", * totalEarn: "390", * status: "1", * earn: { * earnID: "113865", * earnValue: "5", * partnerLabel: "Demo Partner", * earnDate: "01/03/2018", * earnLabel: "Action syst\u00e9matique" * }, * gift: { giftID: "245", value: "20" } * }; */apmApi.triggerAction( tagId: string, properties?: {[s: string]: string});
Return value: 1. Error (see error message) 2. earnObject and userObject
{ earn: earnObject, user: userObject}
Example :
apmApi.triggerAction("writeReview"); // -> Write a review on a businessapmApi.triggerAction("writeReview", {establishment:"restaurant"}); // -> Write a review on a restaurantapmApi.triggerAction("writeReview", {establishment: "restaurant", location: "75000"}); // -> Write a review on a restaurant in Paris
logOut
Logs a user out.
This must be called when a user is logged out of your website.
The SDK will revert to it's non-connected state.
classearnObject { earnID:string|undefined="137189"; earnValue:string|undefined="40"; partnerLabel:string|undefined="nom de la compagnie"; earnDate:string|undefined="12/09/2018"; earnLabel:string|undefined="En créant votre compte";}
Notice
Since the SDK uses WebStorage (localStorage & sessionStorage), please avoid clearing either storages. Clearing them will wipe user data, thus making the user look offline on our SDK, until userClientConnect is called again.
Browser support
Supported on all browsers except IE9 and below.
Desktop:
Mobile:
Stats calculated with data from December 2018 on gs.statcounter.com
More
For any questions, bugs or requests, please contact us on Slack or via email.