Setting Up In-App Messages (Developer Guide)
This guide explains how to set up in-app messaging and client side tracking for Userlist. In addition to this detailed approach, you can also use one of our integration libraries that does most of the heavy lifting for you.
Language / Framework | Links |
---|---|
Ruby | Documentation, Repository |
Ruby on Rails | Documentation, Repository |
We're continuously adding libraries for more languages. If your language or framework isn't listed yet, please follow the guide below.
Adding the JavaScript snippet
In order to use both in-app messages and client side tracking, you have to include a small JavaScript snippet in your application's layout for signed in users.
1
2
<script>window.userlist=window.userlist||function(){(userlist.q=userlist.q||[]).push(arguments)};</script>
<script async data-userlist="insert-generated-user-token-here" src="https://js.userlist.com/v1"></script>
Please note the data-userlist
attribute on the second script
tag.
You have to pass a generated user token in here. This is a unique,
signed token that authenticates the current user with Userlist's
servers. This ensures that only this particular user's record can be
updated and that they are the only ones who can read the messages
intended for them.
Generating user tokens
The user token has to be generated on the server side. This ensures that your Push Key stays secret and nobody else can issue valid user tokens.
The user tokens are JSON Web Tokens (JWT), signed using your application's Push Key.
They require two claims in the payload. Specifically, that's sub
(the
user's unique identifier) and exp
(the token's expiration time). In
addition you must provide the kid
(our Push
Id in the token's header).
There are JWT libraries for almost all programming languages. Nonetheless, the process to generate the tokens is fairly simple, even without a dedicated library.
Ruby Example
Here's an example showing how to generate a token using Ruby and its standard library.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require 'json'
require 'openssl'
require 'base64'
# Url safe Base64 encoding without a trailing =
def base64(string)
Base64.urlsafe_encode64(string).tr('=', '')
end
# Generate a JSON string from the given hash
def json(hash)
JSON.generate(hash)
end
# HMAC signature using the SHA256 algorithm
def hmac256(data, key)
digest = OpenSSL::Digest.new('SHA256')
OpenSSL::HMAC.digest(digest, key, data)
end
push_key = 'EqNgYUpW3oURUGMMU8IDnSWy4SwTLs0p' # Your applications's Push Key
push_id = 'OMNfBvInB8g5AZbwnpiTymlccEYm6nLc' # Your applications's Push Id
payload = {
sub: 'user-1', # The user's unique identifier
exp: Time.now.to_i + 300 # The expiration time as unix timestamp in UTC
}
header = {
kid: push_id,
alg: 'HS256'
}
encoded_header = base64(json(header))
encoded_payload = base64(json(payload))
encoded_header_and_payload = "#{encoded_header}.#{encoded_payload}"
encoded_signature = base64(hmac256(encoded_header_and_payload, push_key))
token = "#{encoded_header}.#{encoded_payload}.#{encoded_signature}"
PHP Example
Here's an example showing how to generate a token using PHP and its standard library.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Url safe Base64 encoding without a trailing =
function base64($string) {
return rtrim(strtr(base64_encode($string), '+/', '-_'), '=');
}
// Generate a JSON string from the given map
function json($data) {
return json_encode($data);
}
// HMAC signature using the SHA256 algorithm
function hmac256($data, $key) {
return hash_hmac('SHA256', $data, $key, true);
}
$push_key = 'EqNgYUpW3oURUGMMU8IDnSWy4SwTLs0p'; // Your applications's Push Key
$push_id = 'OMNfBvInB8g5AZbwnpiTymlccEYm6nLc'; // Your applications's Push Id
$payload = [
'sub' => 'user-1', // The user's unique identifier
'exp' => time() + 300 // The expiration time as unix timestamp in UTC
];
$header = [
'kid' => $push_id,
'alg' => 'HS256',
];
$encoded_header = base64(json($header));
$encoded_payload = base64(json($payload));
$encoded_header_and_payload = "$encoded_header.$encoded_payload";
$encoded_signature = base64(hmac256($encoded_header_and_payload, $push_key));
$token = "$encoded_header.$encoded_payload.$encoded_signature";
JavaScript (Node.js) Example
The following example shows how to generate a token using JavaScript (Node.js) and its crypto library.
This snippet is intended for server side JavaScript. Do not generate the token on the client side, as this would expose your secret Push Key and allow attackers to read and update all of your user's data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var crypto = require('crypto');
// Url safe Base64 encoding without a trailing =
function base64(data) {
return Buffer.from(data)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// Generate a JSON string from the given object
function json(data) {
return JSON.stringify(data)
}
// HMAC signature using the SHA256 algorithm
function hmac256(data, secret) {
return crypto
.createHmac('sha256', secret)
.update(data)
.digest();
}
var pushKey = 'EqNgYUpW3oURUGMMU8IDnSWy4SwTLs0p'; // Your applications's Push Key
var pushId = 'OMNfBvInB8g5AZbwnpiTymlccEYm6nLc'; // Your applications's Push Id
var payload = {
sub: 'user-1', // The user's unique identifier
exp: Number(new Date()) + 300 // The expiration time as unix timestamp in UTC
};
var header = {
kid: pushId,
alg: 'HS256'
};
var encodedHeader = base64(json(header));
var encodedPayload = base64(json(payload));
var encodedHeaderAndPayload = encodedHeader + '.' + encodedPayload;
var encodedSignature = base64(hmac256(encodedHeaderAndPayload, pushKey));
var token = encodedHeader + '.' + encodedPayload + '.' + encodedSignature;
Python Example
This example shows how to generate a token using Python and its standard library.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import base64
import json
import hmac
import hashlib
import time
# Url safe Base64 encoding without a trailing =
def base64_encode(data):
return base64.urlsafe_b64encode(data).replace('=', '')
# Generate a JSON string from the given dictionary
def json_encode(data):
return json.dumps(data)
# HMAC signature using the SHA256 algorithm
def hmac256(data, secret):
return hmac.new(secret, data, hashlib.sha256).digest()
push_key = 'EqNgYUpW3oURUGMMU8IDnSWy4SwTLs0p' # Your applications's Push Key
push_id = 'OMNfBvInB8g5AZbwnpiTymlccEYm6nLc' # Your applications's Push Id
payload = {
'sub': 'user-1', # The user's unique identifier
'exp': time.time() + 300 # The expiration time as unix timestamp in UTC
}
header = {
'kid': push_id,
'alg': 'HS256'
}
encoded_header = base64_encode(json_encode(header))
encoded_payload = base64_encode(json_encode(payload))
encoded_header_and_payload = encoded_header + '.' + encoded_payload
encoded_signature = base64_encode(hmac256(encoded_header_and_payload, push_key))
token = encoded_header + '.' + encoded_payload + '.' + encoded_signature
C# / .NET Example
This example shows how to generate a token using C# and .NET 5.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Collections;
using System.Text.Json;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var pushKey = "EqNgYUpW3oURUGMMU8IDnSWy4SwTLs0p";
var pushId = "OMNfBvInB8g5AZbwnpiTymlccEYm6nLc";
var payload = new Hashtable(){
{ "sub", "user-1" },
{ "exp", DateTimeOffset.Now.ToUnixTimeSeconds() + 300 }
};
var header = new Hashtable(){
{ "kid", pushId },
{ "alg", "HS256" }
};
var encodedHeader = Base64Encode(JsonEncode(header));
var encodedPayload = Base64Encode(JsonEncode(payload));
var encodedHeaderAndPayload = $"{encodedHeader}.{encodedPayload}";
var encodedSignature = Base64Encode(Hmac256(StringToBytes(encodedHeaderAndPayload), pushKey));
var token = $"{encodedHeader}.{encodedPayload}.{encodedSignature}";
Console.WriteLine(token);
}
public static byte[] StringToBytes(string data) {
return System.Text.Encoding.UTF8.GetBytes(data);
}
public static byte[] JsonEncode(object data) {
var json = JsonSerializer.Serialize(data);
return StringToBytes(json);
}
public static string Base64Encode(byte[] data) {
return System.Convert.ToBase64String(data).Replace('/', '_').Replace('+', '-').TrimEnd('=');
}
public static byte[] Hmac256(byte[] data, string secret) {
var hmac = new HMACSHA256(StringToBytes(secret));
return hmac.ComputeHash(data);
}
}
Client side tracking
After adding the tracking script including the generated user token, you're all set to send in-app messages. In addition, the tracking script also allows you to update the user's properties and to track custom events in the client's browser. See this article for the detailed instructions. Please ensure that those calls are made after the included tracking script, either by placing these calls below the script tags in your HTML or by using the page load event to delay execution.
Can I use my Segment snippet?
If you're using our Segment integration, you might be wondering whether their JavaScript snippet will work for sending in-app messages via Userlist. The short answer is no: you have to include the Userlist snippet directly.