Custom Reactions with Permutive Webhooks

Motivation

Permutive provides a variety of ways to react to your data out-of-the-box. With just a few clicks you can set up marketing overlays to target a specific subset of your audience, or send valuable targeting data to your ad-server. But what if you want to build your own reactions on top of Permutive? Some examples of custom reactions are:

  • Trigger personalized emails and push notifications at some point in the future, for example if a week has passed since a user was last active - send them an email to re-engage them.

  • React to a user becoming inactive, for example if a user added some products to their basket but failed to check-out within an hour you may want to set up a special offer for when they return.

  • Pipe real-time data about your audience into your in-house analytics tools, for example whenever a user enters a segment you may want to keep a record of this in your internal database.

These problems can be solved with Permutive's webhook notifications. By setting up a webhook reaction in the Permutive dashboard, you will receive notifications when a user enters or exits a given segment. In this post, we'll demonstrate setting up a webhook for an 'engaged readers' segment and we will write a small Python web server to receive, authenticate and handle the webhook notifications.

Initial Steps

Let's begin by creating our segment in the Permutive dashboard. Our segment will define engaged readers as users who have viewed at least 5 articles:

Next, enable Webhooks for your project from the integrations tab on your project's settings page. When you do this, Permutive will generate and display a secret token:

This secret can be used by your webhook receiver to authenticate requests and ensure that you only process trusted notifications that were sent by Permutive.

Python Example

The next step is to write our web server. This will be responsible for receiving, authenticating and handling webhook notifications sent by Permutive. Permutive's webhook specification can be found in the developer docs. The gist of it is that webhook notifications are sent as HTTP POST requests with a JSON body. Each request will have a Webhook-Signature header which contains a signature generated from the request's body and your secret token. To authenticate the request, our web server needs to generate an SHA-256 digest of the request body using our token, and verify that the generated digest matches the Webhook-Signature header. In addition to handling POST requests, our web server also needs to respond to HEAD request with a 200 OK. This is because Permutive will send a HEAD request to your endpoint to check that it is healthy.

Let's take a look at our Python webhook receiver:

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import hmac  
import hashlib  
import base64

import json

class RequestHandler(BaseHTTPRequestHandler):

    secret = b'70fae6e0-373d-4ddc-be79-7220ccf55324'

    def do_POST(self):
        signature = self.headers.getheader('webhook-signature', 0)
        content_len = int(self.headers.getheader('content-length', 0))

        body = self.rfile.read(content_len)
        digest = hmac.new(self.secret, msg=body, digestmod=hashlib.sha256).hexdigest()

        if (digest == signature):
            # Request authenticated! 
            # We know this request came from Permutive.
            result = json.loads(body)
            user = result["data"]["user_id"]
            segment = result["data"]["segment_id"]
            print(user + " has just entered segment " + segment)

        self.send_response(200)
        self.end_headers()

    def do_HEAD(self):
        self.send_response(200)
        self.end_headers()

def main():  
    port = 8080
    print('Listening on localhost:%s' % port)
    server = HTTPServer(('', port), RequestHandler)
    server.serve_forever()

if __name__ == "__main__":  
    main()

Our implementation is built on top of Python's HTTPServer. Some additional libraries (hmac, hashlib and base64) are used to perform the authentication. Once a webhook notification has been authenticated, we decode the request body as JSON and are able to extract properties such as the user_id and segment_id.

To host our web server, we simply run our python script on a machine with a publicly accessible IP address that accepts HTTP connections on port 8080.

Go Live!

Finally, we create a webhook reaction in the Permutive dashboard. When creating the reaction, we link it to our 'engaged readers' segment and set the webhook endpoint URL to the public IP address of our server.

When you click create, Permutive will check that it can access your web server endpoint. Once the checks have passed, the webhook will go live and you should start seeing webhook notifications hit your server as users enter your segment.

An interesting use of Permutive webhooks that we've seen demand for is the notion of delayed notifications. These are notifications that are configured to arrive after a user has become inactive or not performed an action for a specified period of time.

If you'd like to find out more about how we can help you power personalization on your site or app, then get in touch!