What is the benefit of a webhook?

Listrak's webhooks allow you to send data to a third party site or application in order to seamlessly pass information from your Listrak workflows to other sites. This ability allows you to ensure the same information is present in both systems and take action on this information in your third party systems.

What are some common use cases for webhooks?

Webhooks can be used to pass many different types of information to your third party endpoint location. Use a webhook to easily send data to this location and keep records in sync to make record keeping even easier. This also allows you to utilize data from Listrak in custom reporting in your third party system or power additional marketing solutions, such as direct mail.

You can also use webhooks to send data, such as an order thank you message, to apps, such as Facebook messenger. You can also send data to these apps to trigger notifications or rewards after taking a specific action on your site.

How does a Listrak webhook work?

The webhook uses a POST function to push information from Listrak Workflow to an endpoint in your third party system. You configure the webhook inside the Listrak platform and then direct the webhook to the location of this endpoint with the information.

What happens inside Workflow?

When configuring a webhook action step in Workflow, you will configure a JSON schema to specify the specific fields that will be sent back to the third-party location specified when you integrate the webhook. A contact's email address and phone number are automatically appended to the JSON schema configured. Only the data points associated with the contact will be appended.

You can also determine what occurs if your webhook fails and is not able to reach the third-party location. By default, a contact will be removed from workflow so the data in Listrak and your third-party stays in sync. You can change this setting to move to the next step in the workflow. Errors in the webhook will also be logged in Listrak. At this time it is not possible to re-initiate the webhook action for contacts where it failed.

Configuring a Webhook Integration

Before adding a webhook action step in Workflow you will first create the webhook in Listrak's Integration Manager.

The Integration Manager is found under Manage > Integrations. This can be accessed from both the Workflow and Email channels.

  1. From the integrations list, select Integrate in the Webhook section.

  2. Click Setup Integration.

  3. Provide a name for your webhook.

  4. Provide the URL where the information captured in Workflow should be sent

    ⚠️ The URL must contain the https protocol

  5. Click Save.

  6. Save the HMAC Secret for future reference.

Using a Webhook Action Step in Workflow

The webhook action step is available in all workflow types except Shopify Transactional workflows.

  1. Place the action step in the desired location.

  2. In the properties panel, name the step, if desired.

  3. Select the configured webhook.

  4. Click Edit JSON.

    ⚠️ The JSON must use standard JSON formatting.

  5. In the popup, define your JSON schema to specify what information should be passed via the webhook

    💡 Learn more about testing your JSON schema in the testing section below

  6. Click Apply.

  7. In the properties panel, select what action should occur if a webhook fails and is not able to post the information.

You can now continue configuring your workflow properties and the webhook action step will begin sending the information after the workfow is activated.

Testing a Webhook

A webhook testing service can often help ensure the data is being passed correctly before connecting to your third-party site and activating a workflow. These services allow you to create a webhook that points to a testing location and then simulate the JSON schema that would appear in the workflow action step. You can use this simulation to confirm that the data is being formatted and sent correctly.

Check out the following testing services to get started:

Authenticating a Webhook

Authenticating a webhook provides a way to validate the requests that are being received by your endpoint. This can prevent malicious requests from a third party from being received by your webhook.

The following process can help authenticate your webhook request.

  1. Gather your HMAC and Secret (saved during the setup of your integration).

  2. Read the payload from the request (the body).

  3. Read the request headers to gather:

    1. LTK-Timestamp

    2. LTK-HmacSignature

  4. Add the LTK-Timestamp to the end of the payload

  5. Run the combined timestamp and payload through a SHA256 HMAC algorithm with your secret as the HMAC secret key

  6. Verify your result matches LTK-HmacSignature

When the results match the request to your webhook originated from Listrak.

The second component is to verify the timestamp to prevent potential replay attacks from malicious third party:

  1. Verify LTK-Timestamp is within your allowed tolerance (for example: 15 minutes)

If both of these components are match your expected values your webhook is authenticated.

Authenticating in Python

import base64
import hashlib
import hmac
import datetime

from flask import Flask
from flask import request, abort

app = Flask(__name__)
SECRET = 'YOUR-SECRET-HERE'
BYTE_SECRET = SECRET.encode('UTF-8')


@app.route('/', methods=['POST'])
def webhook_endpoint():
request_data = request.get_data().decode('utf-8')
request_timestamp = str(request.headers['LTK-Timestamp'])
request_hmac = request.headers['LTK-HmacSignature'].encode('utf-8')

# Check that the HMAC is signed correctly to verify that request came from someone who knows the HMAC secret.
my_hmac = compute_hmac(request_data, request_timestamp)
hmac_verified = hmac.compare_digest(my_hmac, request_hmac)
# Check that timestamp is recent to avoid replay attacks.
timestamp_verified = verify_timestamp(request_timestamp)

# If either check fails then exit early.
if not hmac_verified or not timestamp_verified:
abort(401)

# Now you can be sure this request was sent by Listrak in the last 15 minutes!
# ... your code goes here ...

return "Webhook verified", 200


def compute_hmac(data, timestamp):
combined_data = (data + timestamp).encode('utf-8')
digest = hmac.new(BYTE_SECRET, combined_data, hashlib.sha256).digest()
return base64.b64encode(digest)


def verify_timestamp(request_timestamp):
request_datetime = datetime.datetime.fromtimestamp(int(request_timestamp))
fifteen_minutes_ago_datetime = datetime.datetime.now() - datetime.timedelta(minutes=15)
if request_datetime < fifteen_minutes_ago_datetime:
return False
return True


if __name__ == '__main__':
app.run()

Authenticating in C#

using System;
using System.Text;
using System.Security.Cryptography;

// Endpoint read the following headers to compare the computed signature

var hmacSecret = "YOUR-SECRET-HERE";
var timestamp = Request.Headers["LTK-Timestamp"];
var signature = Request.Headers["LTK-HmacSignature"];
var payloadJson = Request.Body;

// Compute the Hmac secret (using GetHmacSignature below) to compare against the extracted signature.
// Ensure the timestamp is within the allowed time.

// Request is verified!
// .. your code goes here ..


private static string GetHmacSignature(string hmacSecret, string payloadJson, string timestamp)
{
var hmacBytes = Encoding.UTF8.GetBytes(hmacSecret);
using HMACSHA256 hmac = new HMACSHA256(hmacBytes);
var combinedBytes = Encoding.UTF8.GetBytes(payloadJson + timestamp);
return Convert.ToBase64String(hmac.ComputeHash(combinedBytes.ToArray()));
}

Authenticating in JavaScript

// Simple Node Express webhook example
// Requires installing express: 'npm install --save express body-parser'
const express = require('express');
const bodyParser = require('body-parser')
const crypto = require('crypto');
const app = express();


app.use('/webhooks/path', bodyParser.text({ type: '*/*' }), (req, res, next) => {

const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET
const timeStamp = req.header('LTK-Timestamp')
const webhook_payload = req.body
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET)
const webhookDigest = hmac.update(webhook_payload + timeStamp).digest('hex')

const computedSignature = `${webhookDigest}`
const requestSignature = req.header('LTK-HmacSignature')

// if requestSignature and computedSignature do not match, you have an invalid request.
// if timeStamp is not within the allowed time, you have an invalid request.

// Request is verified!
// .. your code goes here .

});

Did this answer your question?