Business Messenger Webpush - SDK
Supports the following browsers caniuse.com/push-api.
Prerequisites
To proceed with the integration of HPRO Web Push SDK to your HTTPS website you must meet the following conditions:
- Locate your formUuid from the HORISEN Business Messenger Application,
- Download or use HPRO webpush SDK.
To use our Webpush, your site needs to have SSL certificate or you can use localhost domain during development.
1. Introduction
Webpush SDK is a javascript library that provides subscription mechanism for Webpush notifications for your website/domain.
After a visitor subscribes you will be able to notify him with updates using standard the Business Messenger campaigns.
The SDK can be configured either as a small subscription button widget or used directly from javascript so that you can build your own custom subscription forms and collect some other information to be populated per contact in the Business Messenger Contact Manager.
2. Requirements
- Register your HORISEN PRO account and confirm it.
- Gain access over the Business Messenger Application by contacting your administrator.
- In the Business Messenger Application go to the Web > Webpush section, create a Webpush Rule and find SDK Parameters for your Rule (UUID and Webpush Public Key) which you will use later in configuring the SDK.
3. Setup
Download SDK and Service worker files and put them on your server. You can download them separately or download hpro-wp.zip and extract it.
Version | Bundle | SDK | Service Worker |
---|---|---|---|
1.3.0 | hpro-wp.zip | hpro-wp-sdk.min.js | hpro-wp-sw.min.js |
1.2.0 | hpro-wp.zip | hpro-wp-sdk.min.js | hpro-wp-sw.min.js |
1.1.0 | hpro-wp-sdk.min.js | hpro-wp-sw.min.js | |
1.0.0 | hpro-wp-sdk.min.js | hpro-wp-sw.min.js |
Include SDK script in your page:
index.html
<script async type="text/javascript" src="hpro-wp-sdk.min.js" async></script>
3.1 Service Worker
Standalone
If you have no service worker defined, you can use our SDK as a standalone solution:
Put our hpro-wp-sw.min.js in the root of your website.
Existing
Edit your service-worker.js and import a script which you have downloaded.
service-worker.js
importScripts("hpro-wp-sw.min.js");
3.2 SDK
Initialize the Webpush SDK:
// initial code only done once in entire website
var hproWebPush = hproWebPush || [];
// asynchronously initialize the sdk for the first time
hproWebPush.push(function () {
// before all init first
hproWebPush.init({
workerFile: 'hpro-wp-sw.min.js', // or 'service-worker.js' in case you are using your own service worker
apiUrlPrefix: 'https://api.YOUR_BM_DOMAIN',
apiEndpointFormat: '/forms/{formUuid}/activities',
formUuid: 'YOUR_FORM_UUID',
applicationServerKey: 'YOUR_WEBPUSH_PUBLIC_KEY'
}).then(function initSuccess(_successData) {
// code if everything went fine
}, function initError(_errorData) {
// FrontEnd Subscription, Notification API's are not available
// or some other error
});
});
formUuid (YOUR_FORM_UUID) and applicationServerKey (YOUR_WEBPUSH_PUBLIC_KEY) parameters need to be replaced with real values for your Opt-in/Opt-out Rule from the Web > Webpush section of the Business Messenger app.
3.3 Webpush on Apple Mobile Devices (iOS, iPadOS)
Starting with iOS/iPadOS 16.4, Apple supports standard webpush notifications, but there are some specific steps required to get it working: tst
-
Home Screen Web Apps: Notifications only work if your website is started as a so-called "Home Screen web apps".
-
Manifest File:
- Your website needs a manifest.json file with the right properties set. You can use tools like www.simicart.com/manifest-generator.html to generate it, or do it manually per specs developer.mozilla.org/en-US/docs/Web/Manifest.
- Place this file in the root directory of your website.
-
Include a link to it in the HTML section:
<link rel="manifest" href="manifest.json"/>
-
JavaScript Functions:
-
Your javascript logic and content should be adopted to support iOS use cases. You can use these helper function to achieve this:
function isIOS() { const userAgent = navigator.userAgent || navigator.vendor || window.opera; return /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream; } function isRunningAsWebApp() { return window.navigator.standalone === true; }
-
Then implement a similar flow (pseudo code ahead):
let ios = isIOS() if (!ios || isRunningAsWebApp()) { // ... init webpush sdk normally } else if (ios){ // present a banner to invite iOS/iPadOS users to add your webapp to the Home Screen and run from it, here are some UI ideas https://web.dev/articles/promote-install }
-
The iOS visitor is expected to:
- Visit your website on your Safari browser on a mobile Apple device on 16.4+
- Click on the "Share" button of their Safari browser on a mobile device.
- Click on the "Add to home screen" option.
- Save the app on their device.
- Open it the app from the home screen.
- Subscribe to notifications (they must click a subscribe button before a native permission prompt can be displayed).
4. Usage
Our SDK is defined in mind to be compatible with the JS Array structure.
Since SDK may not be available yet at the time of the calling method, Arrays allow us to postpone calling of those function when page is ready.
Every method is pushed to the array and executed in FIFO method. This is why you always use the .push method as a wrapper of set of methods.
Our SDK methods can be called in two ways.
4.1 Async Call
General usage:
hproWebPush.push(function () {
hproWebPush.${functionName}(param1, param2);
});
Without Promise, and with callback arguments:
hproWebPush.push([
'init',
hproWebPushConfig,
function initSuccess () { /*...*/},
function initError () { /*...*/},
]);
// optional hproWebPush.push function call
4.2 Sync Call
General usage:
hproWebPush.push(['${functionName}', param1, param2]);
Method specific usage with callbacks:
hproWebPush.push(function () {
hproWebPush.init(
hproWebPushConfig,
function initSuccess () { /*...*/ },
function initError () { /*...*/ }
);
// optional hproWebPush function call or any other
});
Method specific usage with Promise, without callbacks:
hproWebPush.push(function () {
hproWebPush.init(
hproWebPushConfig
).then(function initSuccess () { /*...*/})
.catch(function initError () { /*...*/});
// optional hproWebPush function call or any other
});
5. Configuration
Properties:
Property | Type | Usage | Default | Values | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
applicationServerKey | String | mandatory | VAPID key | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
apiUrlPrefix | String | optional | https |
Example: https |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
apiEndpointFormat | String | optional | /forms/{formUuid}/activities |
Example: /services/{serviceUuid}/forms/{formUuid}/activities |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
apiTestEndpointFormat | String | optional | /forms/{formUuid}/test | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
identifier | String | optional | null | undefined | If you can identify the user with contact UUID, before SDK initialization, you can set it up here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceUuid | String | mandatory | If used, provide the BM account UUID. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
formUuid | String | mandatory | Form UUID that is used to identify the subscription. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workerFile | String | mandatory | service-worker.js | File name of the service worker. Example: service-worker.js |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data | Object | optional | {} | Custom data to send. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers | Object | optional | {} | Custom headers to send. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
whenUnsubscribed | String | optional | keep_identity | keep_identity remove_identity |
keep_identity or remove_identity Default: keep_identity By default, when unsubscribe is finished, in local storage, identifier exist. After subscription, contact will be updated. When remove_identity is set, after unsubscribe local storage identifier will be deleted. After subscription, new contact will be created. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
autoSubscribe | Boolean | optional | false | By default when SDK use notifyButton - autoSubscribe is true, in advanced mode is false added in version 1.1.0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logEnable | Boolean | optional | false | Enable log which give use detailed subscription info
added in version 1.1.0 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
notifyButton | Object | optional | null | undefined | false |
|
Usage:
var hproWebPushConfig = {
workerFile: 'service-worker.js',
applicationServerKey: "BCmti7ScwxxVAlB7WAyxoOXtV7J8vVCXwEDIFXjKvD-ma-yJx_eHJLdADyyzzTKRGb395bSAtxlh4wuDycO3Ih4",
apiUrlPrefix: 'https://api.YOUR_BM_DOMAIN',
apiEndpointFormat: '/services/{serviceUuid}/forms/{formUuid}/activities',
apiTestEndpointFormat: '/services/{serviceUuid}/forms/{formUuid}/test',
formUuid: null,
serviceUuid: null,
identifier: null,
data: {},
headers: {}
};
6. Methods
6.1 init
init(config, successCallback, errorCallback)
Call this function from your page where you want to use hproWebPush.
- Do not call this method twice
- This call is required before any other method is called
Properties:
Property | Type | Usage | Description |
---|---|---|---|
config | Object | mandatory | Configuration |
successCallback | Function | optional | Success Callback |
errorCallback | Function | optional | Error Callback |
Return:
Promise
Usage:
var hproWebPush = hproWebPush || [];
hproWebPush.push(function () {
hproWebPush.init({
formUuid: 'YOUR_FORM_UUID',
applicationServerKey: 'YOUR_WEBPUSH_PUBLIC_KEY'
}, function () {
console.log('initialized');
}, function(){
console.log('Not initialized');
});
});
Methods which are listed in documentation, can be used after init method is called and hproWebPush object is created.
6.2 subscribe
subscribe(contactData, customHeader, successCallback, errorCallback)
The method does a subscription process.
Properties:
Property | Type | Description |
---|---|---|
contactData | Object | |
customHeader | Object | |
successCallback | Function | Promise resolving. successCallback(successResponse) successResponse:
|
errorCallback | Function | Promise rejection. errorCallback(errorResponse) errorResponse:
|
Return:
Promise
Usage:
hproWebPush.subscribe().then(function (successResponse) {
console.log('subscribed', successResponse);
}).catch(function (errorResponse) {
console.log('not subscribed', errorResponse);
});
6.3 isSubscribed
isSubscribed(successCallback, errorCallback)
The method checks to see if you are already subscribed. Each callback will return the permission state.
Properties:
Property | Type | Description |
---|---|---|
successCallback | Function | Promise resolving. successCallback(successResponse) successResponse: Resolves with notification permission status. |
errorCallback | Function | Promise rejection. errorCallback(errorResponse) errorResponse: Rejects with notification permission status. |
Return:
Promise
Usage:
hproWebPush.isSubscribed().then(function (successResponse) {
console.log('subscribed', successResponse);
}).catch(function (errorResponse) {
console.log('not subscribed or no permission granted', errorResponse);
});
6.4 update
(contactData, customHeaders, successCallback, errorCallback)
The method updates current subscription.
Properties:
Property | Type | Description |
---|---|---|
contactData | Object | |
customHeaders | Object | |
successCallback | Function | Promise resolving. successCallback(successResponse) successResponse:
|
errorCallback | Function | Promise rejection. errorCallback(errorResponse) errorResponse:
|
Return:
Promise
Usage:
hproWebPush.update({ identifier: 'YOUR_CONTACT_ID' }).then(function (successResponse) {
console.log('updated', successResponse);
}).catch(function (errorResponse) {
console.log('not updated', errorResponse);
});
6.5 permit
permit(successCallback, errorCallback)
The method triggers the browsers notification permission dialog.
Properties:
Property | Type | Description |
---|---|---|
successCallback | Function | Promise resolving. successCallback(successResponse) successResponse: Resolves with notification permission status. |
errorCallback | Function | Promise rejection. errorCallback(errorResponse) errorResponse: Rejects with notification permission status. |
Return:
Promise
Usage:
hproWebPush.permit().then(function (successResponse) {
console.log('permitted', successResponse);
}).catch(function (errorResponse) {
console.log('not permitted', errorResponse);
});
6.6 unsubscribe
(contactData, customHeaders, successCallback, errorCallback)
The method unsubscribes current subscription.
Properties:
Property | Type | Description |
---|---|---|
contactData | Object | |
customHeaders | Object | |
successCallback | Function | Promise resolving. successCallback(successResponse) successResponse:
|
errorCallback | Function | Promise rejection. errorCallback(errorResponse) errorResponse: Rejects with notification permission status. |
Return:
Promise
Usage:
hproWebPush.unsubscribe().then(function (responseCode) {
console.log('unsubscribed', responseCode);
}).catch(function (responseCode) {
console.log('not unsubscribed', responseCode);
});
7. Examples
7.1 Contact Data and Auto Identifier
In this example we only require End-User to enter his name for subscription.
The end result is that after successful subscription user is provided with identifier which will be saved for later use in browser's local storage.
When subscription token is expired and identifier exists in browser's local storage, SDK can identify and it will update existing contact.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpush Basic Example</title>
</head>
<body>
<button onclick="subscribe(event)">Subscribe</button>
<button onclick="unsubscribe(event)">Unsubscribe</button>
<script async type="text/javascript" src="hpro-wp-sdk.min.js" async></script>
<script>
var hproWebPush = hproWebPush || [];
hproWebPush.push(function () {
// before all init first
hproWebPush.init({
workerFile: 'hpro-wp-sw.min.js',
whenUnsubscribed: 'remove_identity',
formUuid: 'd44795cb-af37-4edb-b324-df9d0f720679',
applicationServerKey: 'BIsHK3ZIGQ6qylk1TkdHuxGZ2f1qNdPIQd+y61J7UA1uFGlJw9IZK2yD4/uRi+rJItEBc6HV1OewS64932acGMs=',
notifyButton: {
enable: true,
position: 'top-left'
}
}).then(function (successResponse) {
console.log('initialized', successResponse);
}, function (errorResponse) {
console.log('Not initialized', errorResponse);
});
});
function subscribe() {
const _myFullname = prompt('John Doe');
const _fullnameParts = _myFullname.split(' ');
// webpush subscription
hproWebPush.subscribe({
first_name: _fullnameParts[0],
last_name: _fullnameParts[1]
}).then(function (successResponse) {
console.log('subscribed', successResponse);
}, function (errorResponse) {
console.warn('denied', errorResponse);
});
}
function unsubscribe() {
hproWebPush.unsubscribe().then(function (successResponse) {
console.log('unsubscribed', successResponse);
}, function (errorResponse) {
console.log('not unsubscribed', errorResponse);
});
}
</script>
</body>
</html>
7.2 Existing Identifier
In this example we force SDK to use existing contact identifier (contact UUID). E.g. if you are building a user portal, you should store BM contact UUID along with other user profile information. This way you will be able to specify it in Webpush SDK parameters.
We have already identified the contact and we have initialized SDK with his identifier.
Identifier will also be saved for later use in browser's local storage.
The end result is that after successful subscription the same user is updated with latest subscription token.
When subscription token is expired, SDK can identify and refresh subscription token.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpush Basic Example</title>
</head>
<body>
<button onclick="subscribe(event)">Subscribe</button>
<button onclick="unsubscribe(event)">Unsubscribe</button>
<script async type="text/javascript" src="hpro-wp-sdk.min.js" async></script>
<script>
var hproWebPush = hproWebPush || [];
hproWebPush.push(function () {
// before all init first
hproWebPush.init({
workerFile: 'hpro-wp-sw.min.js',
whenUnsubscribed: 'remove_identity',
identifier: 'd354fe67-87f2-4438-959f-65fde4628787',
formUuid: 'd44795cb-af37-4edb-b324-df9d0f720679',
applicationServerKey: 'BIsHK3ZIGQ6qylk1TkdHuxGZ2f1qNdPIQd+y61J7UA1uFGlJw9IZK2yD4/uRi+rJItEBc6HV1OewS64932acGMs=',
}).then(function (successResponse) {
console.log('initialized', successResponse);
}, function (errorResponse) {
console.log('Not initialized', errorResponse);
});
});
function subscribe() {
const _myFullname = prompt('John Doe');
const _fullnameParts = _myFullname.split(' ');
// webpush subscription
hproWebPush.subscribe({
first_name: _fullnameParts[0],
last_name: _fullnameParts[1]
}).then(function (successResponse) {
console.log('subscribed', successResponse);
}, function (errorResponse) {
console.warn('denied', errorResponse);
});
}
function unsubscribe() {
hproWebPush.unsubscribe().then(function (successResponse) {
console.log('unsubscribed', successResponse);
}, function (errorResponse) {
console.log('not unsubscribed', errorResponse);
});
}
</script>
</body>
</html>
7.3 Auto Subscribe
Auto Subscribe will only work when user has given browser notification permissions and token has expired at some point.
It will not work on first user visit, because user needs to click on notification button to be asked for browser notification permissions, and grant them.
This all happens during the init procedure.
On every later visit user will be updated with the new subscription token.
It works in both cases: existing contact identifier or auto contact identifier.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpush Basic Example</title>
</head>
<body>
<button onclick="subscribe(event)">Subscribe</button>
<button onclick="unsubscribe(event)">Unsubscribe</button>
<script async type="text/javascript" src="hpro-wp-sdk.min.js" async></script>
<script>
var hproWebPush = hproWebPush || [];
hproWebPush.push(function () {
// before all init first
hproWebPush.init({
workerFile: 'hpro-wp-sw.min.js',
whenUnsubscribed: 'remove_identity',
identifier: 'd354fe67-87f2-4438-959f-65fde4628787',
autoSubscribe: true,
formUuid: 'd44795cb-af37-4edb-b324-df9d0f720679',
applicationServerKey: 'BIsHK3ZIGQ6qylk1TkdHuxGZ2f1qNdPIQd+y61J7UA1uFGlJw9IZK2yD4/uRi+rJItEBc6HV1OewS64932acGMs=',
}).then(function (successResponse) {
console.log('initialized', successResponse);
}, function (errorResponse) {
console.log('Not initialized', errorResponse);
});
});
function subscribe() {
const _myFullname = prompt('John Doe');
const _fullnameParts = _myFullname.split(' ');
// webpush subscription
hproWebPush.subscribe({
first_name: _fullnameParts[0],
last_name: _fullnameParts[1]
}).then(function (successResponse) {
console.log('subscribed', successResponse);
}, function (errorResponse) {
console.warn('denied', errorResponse);
});
}
function unsubscribe() {
hproWebPush.unsubscribe().then(function (successResponse) {
console.log('unsubscribed', successResponse);
}, function (errorResponse) {
console.log('not unsubscribed', errorResponse);
});
}
</script>
</body>
</html>
8. Contact Data
"Contact Data" is data that you can send to our service when subscribe method is triggered. With that way of gathering data, you will have more information about your subscriber.
Key | Type | Values | Description |
---|---|---|---|
first_name | String | First Name | |
last_name | String | Last Name | |
nick_name | String | Nick Name | |
second_name | String | Second Name | |
gender | String | male female |
Gender Female or male |
birthday | String | Birthday Format: 2018-01-03 |
|
salutation | String | Salutation | |
fax | String | Fax | |
language | String (lowercase) |
en.wikipedia.org/wiki/List_of_ISO_639-1_codes | Language Example: 'en' for English |
nationality | String (lowercase) |
en.wikipedia.org/wiki/ISO_3166-1 | Nationality Example: "GB" for United Kingdom |
mobile | String | Mobile Example: +41 78 123 45 67 |
|
phone | String | Phone Example: +41 78 123 45 67 |
|
title | String | Title | |
zip | String | ZIP | |
address | String | Address | |
city | String | City | |
region | String | Region | |
country | String (uppercase) |
en.wikipedia.org/wiki/ISO_3166-1 | country Example: "GB" for United Kingdom |
b_address | String | Business address | |
b_city | String | Business city | |
b_company | String | Company name | |
b_country | String (uppercase) |
en.wikipedia.org/wiki/ISO_3166-1 | Business Country Example: 'DE' for Germany |
b_department | String | Business Department | |
b_email | String | Business Email | |
b_job_title | String | Job Title | |
b_mobile | String | Business Mobile Example: +41 78 123 45 67 |
|
b_phone | String | Business Phone Example: +41 78 123 45 67 |
|
b_reception_code | String | Business Reception code | |
b_region | String | Business Region | |
b_zip | String | Business ZIP |
9. Change Log
9.1 v1.3.0
2024-07-25
- Optimized subscribe flow
- Optimized unsubscribe flow
- Fixed button subscription state
- Bundles are minimized
9.2 v1.2.0
2024-03-20
- Removed Axios (http client) from bundle
9.3 v1.1.0
2020-02-10
- General optimizations
9.4 v1.0.0
2018-01-15
- Initial release