XF 2.3 Automate workflows with webhooks

hys_5_make_create_webhook.png
hys_5_spoiler.png xenforo.com_community_threads_a-first-look-at-xenforo-2-3.216641_ (1).png xenforo.com_community_threads_a-first-look-at-xenforo-2-3.216641_.png

In what is probably one of the worst kept secrets in XenForo 'Have you seen...?' history, the eagle eyed amongst you may have picked up on one or two... or three... clues that we may be talking about this soon, and the day has finally arrived! Today we're excited to show you our take on the highly requested webhook implementation in XenForo.

For those of you who haven't heard of webhooks before, they are a powerful utility that allow one application or service to send information to another when certain events occur. These can be everyday actions such as when making a payment for access to a product or service, or more specific implementations such as having a new Thread from your forum posted to Discord automatically.

It is likely that even if you're not a developer type person then you have utilised or encountered webhooks in one way or another at some point without realizing.

Here at XenForo, we automate a lot of our workflow using webhooks, some of which may be obvious, others less so. For example, we receive a webhook from GitHub every time that we fix a bug report - this is what automatically marks bug reports as fixed. Another example, is we send a webhook to Slack every time someone posts a bug report or reports content.

Webhooks as a general concept, can be a very flexible tool with an endless amount of use cases, the ability to send webhooks whenever certain events occur on your forum to another system is going to be something you can take advantage of starting with XenForo 2.3.

Now while webhooks may appear on the surface to be something targeted towards developers, there are a number of fantastic third party automation services which are capable of receiving webhooks and triggering actions. These services, such as IFTTT, Make, and Zapier, offer a convenient and user friendly way to automate and integrate applications within your website with thousands of integrations already available.

Closer integration with one or more of these services is being considered for a future release, but all three of the above examples do accept webhooks as a trigger.

As ever, there's a lot to talk about in this one so feel free to jump to a specific section below:
We're excited to hear what you think about webhooks coming to XenForo and what kind of use cases you'll be exploring. Let us know below.

Have you had enough yet? We haven't. There's more to come next week!
 

Configuring XenForo to send webhooks​

In the following walkthrough, we're just going to show you the steps you can take to setup a webhook which will be sent on a specific event, and demonstrate receiving that through a website, https://webhook.site/.

You can find Webhooks in your admin control panel under Setup > Webhooks. To make your first webhook you will click "Add webhook". The add page is roughly split into three parts. The first lets you define the important bits like a title, and a target URL:

hys_5_setup1.png

The Target URL is the URL of the script/service that is going to receive your webhook.

The Secret is a value that is sent in the XF-Webhook-Secret request header when sending the webhook. This is optional but if you choose to use it in your own webhook receiving script then you can use it to ensure the request contains the correct secret and is authenticated.

Scrolling down a little gives you a list of content types:

hys_5_setup2.png


Note: The event list here has not yet been finalised and more events will be added between now and the final release.

This is where you can specify one or more events across different content types you wish to trigger webhooks for. When you expand a content type, you'll be faced with a few options, first and foremost you have a decision to make as to which events you would like to trigger your webhook.

For each content type you can either not send any events, send all events, or only send on specific events.

hys_5_setup3.png


For this example, we will only send on thread_insert.

Some content types also allow you to specify additional filtering criteria. You might, for example, only be interested threads posted in a specific forum.

The third section are the final few settings you can change before saving:

hys_5_setup4.png


You can change how the webhook is encoded. By default this is application/json but you may also want to use x-www-form-urlencoded instead.

You can toggle off "Enable SSL verification" here if you have to, but for the most part you will leave this enabled unless you have a specific reason.

Finally, you can set the webhook to active / inactive.

Once this is saved, all that is left to do is to post a new thread to trigger a webhook, and then use webhook.site to see what data we've sent... here it is!

JSON:
{
  "content_type": "thread",
  "event": "insert",
  "content_id": 216847,
  "data": {
    "custom_fields": {},
    "discussion_open": true,
    "discussion_state": "visible",
    "discussion_type": "article",
    "first_post_id": 1649025,
    "first_post_reaction_score": 0,
    "FirstPost": {
      "attach_count": 0,
      "is_first_post": true,
      "is_last_post": true,
      "is_reacted_to": false,
      "last_edit_date": 0,
      "message": "[COLOR=rgb(224, 224, 224)]Welcome to the first in our Have you seen...? series for XenForo 3.0\n\n[MEDIA=youtube]dQw4w9WgXcQ[/MEDIA][/COLOR]",
      "message_parsed": "<span style=\"color: rgb(224, 224, 224)\">Welcome to the first in our Have you seen...? series for XenForo 3.0<br />\n<br />\n<div data-template-name=\"_media_site_embed_youtube\" class=\"bbMediaWrapper\" data-media-site-id=\"youtube\" data-media-key=\"dQw4w9WgXcQ\">\n\t<div class=\"bbMediaWrapper-inner\">\n\t\t<iframe src=\"https://www.youtube.com/embed/dQw4w9WgXcQ?wmode=opaque\"\n\t\t\t\tloading=\"lazy\"\n\t\t\t\twidth=\"560\" height=\"315\"\n\t\t\t\tframeborder=\"0\" allowfullscreen=\"true\"></iframe>\n\t</div>\n</div></span>",
      "message_state": "visible",
      "position": 0,
      "post_date": 1697446950,
      "post_id": 1649025,
      "reaction_score": 0,
      "thread_id": 216847,
      "User": {
        "avatar_urls": {
          "o": "https://xenforo.com/community/data/avatars/o/11/11388.jpg?1696499135",
          "h": "https://xenforo.com/community/data/avatars/h/11/11388.jpg?1696499135",
          "l": "https://xenforo.com/community/data/avatars/l/11/11388.jpg?1696499135",
          "m": "https://xenforo.com/community/data/avatars/m/11/11388.jpg?1696499135",
          "s": "https://xenforo.com/community/data/avatars/s/11/11388.jpg?1696499135"
        },
        "is_staff": true,
        "location": "UK",
        "message_count": 33705,
        "profile_banner_urls": {
          "l": "https://xenforo.com/community/data/profile_banners/l/11/11388.jpg?1696466377",
          "m": "https://xenforo.com/community/data/profile_banners/m/11/11388.jpg?1696466377"
        },
        "question_solution_count": 98,
        "reaction_score": 40385,
        "register_date": 1318189653,
        "signature": "",
        "trophy_points": 823,
        "user_id": 11388,
        "user_title": true,
        "username": "Chris D",
        "view_url": "https://xenforo.com/community/index.php?members/chris-d.11388/",
        "vote_score": 332
      },
      "user_id": 11388,
      "username": "Chris D",
      "view_url": "https://xenforo.com/community/index.php?posts/1649025/",
      "warning_message": ""
    },
    "Forum": {
      "breadcrumbs": [
        {
          "node_id": 1,
          "title": "Official forums",
          "node_type_id": "Category"
        }
      ],
      "description": "This forum spotlights some of XenForo's interesting features. Spotlights on features in upcoming releases will be posted here.",
      "display_in_list": true,
      "display_order": 200,
      "image_url": "",
      "node_id": 3,
      "node_name": "have-you-seen",
      "node_type_id": "Forum",
      "parent_node_id": 1,
      "title": "Have you seen...?",
      "type_data": {
        "allow_posting": true,
        "article": {
          "display_style": "preview",
          "expanded_snippet": 250,
          "expanded_per_page": 13
        },
        "can_create_thread": true,
        "can_upload_attachment": true,
        "discussion_count": 135,
        "forum_type_id": "article",
        "is_unread": true,
        "last_post_date": 1697446950,
        "last_post_id": 1649025,
        "last_post_username": "Chris D",
        "last_thread_id": 216847,
        "last_thread_prefix_id": 0,
        "last_thread_title": "What's new in XenForo 3.0?",
        "message_count": 18398,
        "min_tags": 0,
        "require_prefix": false
      },
      "view_url": "https://xenforo.com/community/index.php?forums/have-you-seen/"
    },
    "highlighted_post_ids": [],
    "is_first_post_pinned": true,
    "is_search_engine_indexable": true,
    "last_post_date": 1697446950,
    "last_post_id": 1649025,
    "last_post_user_id": 11388,
    "last_post_username": "Chris D",
    "node_id": 3,
    "post_date": 1697446950,
    "prefix_id": 0,
    "reply_count": 0,
    "sticky": false,
    "tags": [],
    "thread_id": 216847,
    "title": "What's new in XenForo 3.0?",
    "User": {
      "avatar_urls": {
        "o": "https://xenforo.com/community/data/avatars/o/11/11388.jpg?1696499135",
        "h": "https://xenforo.com/community/data/avatars/h/11/11388.jpg?1696499135",
        "l": "https://xenforo.com/community/data/avatars/l/11/11388.jpg?1696499135",
        "m": "https://xenforo.com/community/data/avatars/m/11/11388.jpg?1696499135",
        "s": "https://xenforo.com/community/data/avatars/s/11/11388.jpg?1696499135"
      },
      "is_staff": true,
      "location": "UK",
      "message_count": 33705,
      "profile_banner_urls": {
        "l": "https://xenforo.com/community/data/profile_banners/l/11/11388.jpg?1696466377",
        "m": "https://xenforo.com/community/data/profile_banners/m/11/11388.jpg?1696466377"
      },
      "question_solution_count": 98,
      "reaction_score": 40385,
      "register_date": 1318189653,
      "signature": "",
      "trophy_points": 823,
      "user_id": 11388,
      "user_title": true,
      "username": "Chris D",
      "view_url": "https://xenforo.com/community/index.php?members/chris-d.11388/",
      "vote_score": 332
    },
    "user_id": 11388,
    "username": "Chris D",
    "view_count": 0,
    "view_url": "https://xenforo.com/community/index.php?threads/whats-new-in-xenforo-3-0.216847/"
  }
}

Anyone who has played around with the REST API may find the format of the webhook here somewhat familiar and that's for a very good reason: behind the scenes, the building of webhook results is the same code we use to build API responses. You are able to fine tune the results to include/exclude certain keys depending on the type of result being rendered, but for the most part the responses will be the same.

At the top level of webhook results you will see the content_type, event and content_id keys, and the remaining data related to the content is under the data key.

The webhook request also includes various information in headers:

hys_5_webhook.png


You can see here the webhook secret value, along with a few additional headers you can use, if you wish, before parsing the full content, such as xf-webhook-event and xf-content-type.

This is all very cool, but let's take a look at how you might be able to use this in the real world.
 
Last edited:

A real world webhook example​

For the purposes of this example, we're going to use Make but you can achieve similar results with IFTTT and Zapier.

We are now going to automatically post a message to a Discord server channel when a new thread is created in an announcement forum.

In the Make scenario editor, we will click the "Add" button, find the "Webhooks" application and then select the "Custom webhook" trigger:

1697451399331.webp
1697451543178.png


We then click "Create webhook" and fill in some basic details. You can specify IP restrictions here as a security measure:

hys_5_make_create_webhook.png


Rather than specifying an IP address here, let's click "Show advanced settings" and check "Get request headers". This will enable us to verify that the webhook secret we send along with the request is correct.

This will then give you your webhook address. We will modify our existing webhook to point the Target URL to the new Make webhook URL and update the filters to use the thread_insert event when something is posted in the "Announcements" forum.

To get the most out of Make, it likes to understand your data structure. The easiest way to do that in this case is create a test thread, or wait for a new thread to be created.

Before configuring the webhook secret filter, we'll now click "Add" to add a new module, search for "Discord" and click "Send a message".

hys_5_make_discord_create.png


This is where you are now able to configure and connect to your Discord server. Simply click "Create a connection", give it a name and complete the login process to authorize your Make account to connect to your Discord account, selecting the target Discord server.

hys_5_make_discord_auth.png


Once authorized, the Make (or Integromat) bot will be added to your server. You can then go back to Make in order to configure exactly what you want to happen when the webhook is received.

Ensuring "Send message to a channel" is selected, you can now specify your channel name as the target for the incoming thread. You also need to populate the "Message" field with what you want to be posted.

This can be a completely static message, if you want, but why do that when you can use data from the incoming webhook for your message?

hys_5_make_discord_message.png


Once you click "OK" that's all you need to do. But let's just take a quick look at filters. To do this you just click on the icon between the two modules, your webhook and the Discord module. This allows you to "Set up a filter".

hys_5_make_filter_webhook_secret.png


We're going to use the same webhook secret we set up earlier, and say that the xf-webhook-secret header must be equal to that. You can add a bunch of other filters and conditions here too. While within XenForo you are able to specify certain conditions, such as the forum, you could just as easily set up those filters within Make itself.

And all that's left to do is wait for the threads to start being posted straight to your Discord:

hys_5_make_discord_rick_roll.png
 
Aside from Discord, does anyone know of any 3rd party sites/scripts that are designed to accept webhook messages? (wordpress?)

Also - dumb question amnesty requested here but, are webhook messages in some sort of industry standard format?
 
Aside from Discord, does anyone know of any 3rd party sites/scripts that are designed to accept webhook messages? (wordpress?)

Also - dumb question amnesty requested here but, are webhook messages in some sort of industry standard format?
There's no industry standard which is why, unless you're writing your own webhook receiver, you will want to use a service like IFTTT, Zapier, or Make (there are others).

These provide a layer of abstraction between one service and another, translating the payload format from one service into the payload format required by another service.

There are literally endless integrations.

@Kier and I were musing yesterday whether we could make his office lights flash when a post is made in a particular forum. The answer is, yes.
 
Great news! I've been wanting to look into something like using Zapier for a while now on one of my add-ons. This will definitely make that a lot more likely scenario for me to be able to figure out!
 
This is fantastic.

Out of curiosity Chris, for User events I can assume one of them is registration, correct? Might be asking the obvious but just figured I'd check :).

Great work! This is honestly my number one feature I wanted in XenForo.
Yes, absolutely. Essentially all of those content types listed have create, update and delete events. Some of the content have more events, like thread supports featuring and unfeaturing.

More should be added between now and release where appropriate.
 
Last edited:
Aside from Discord, does anyone know of any 3rd party sites/scripts that are designed to accept webhook messages? (wordpress?)

There are so many possibilities and the biggest thing in my opinion, is that this opens those possibilities for non-developers.

  • New report? Post it to slack/discord chat.
  • New user? Add them to a mailing list (when they agree to it)
  • User gets awarded a special unique trophy? Send them an email in a Gmail thanking them
  • user purchases a product/user upgrade? Wait X amount of time to send email asking for review somewhere
  • Auto post specific threads to Facebook/twitter

This can open up so much for a variety of communities.
 
Last edited:
Top Bottom