Meta Pixel & Conversions API

:information_source: Summary In a few words, what does this plugin do?
:hammer_and_wrench: Repository Link Discourse Meta Pixel & Conversions API Plugin
:open_book: Install Guide How to install plugins in Discourse

The usual way to add the Meta Pixel to Discourse is to paste the base code into a theme component. That fires fbq('track', 'PageView') once on document load, and Discourse never reloads the document, so you get one PageView per visit no matter how many topics someone reads. This plugin fires per navigation, adds content and conversion events, and sends a server-side copy through the Conversions API so events survive ad blockers.

Why not just use a theme component?

A theme component runs in the browser only, which has three consequences.

Ad blockers and Safari’s ITP remove a meaningful share of browser events, and you can’t tell which ones are missing. It can’t do the Conversions API at all, because that needs an access token and there’s nowhere in a theme component to put a secret that visitors can’t read. And it fires everywhere it’s injected, including private messages, /admin and password reset pages.

If all you want is a PageView for a retargeting audience, a theme component is genuinely enough and takes two minutes. This is for conversion quality.

Do I need this for my forum?

Probably not. Pixel and CAPI are designed to help you track conversions and create advertising audiences. While it can give you some analytical data, the Discourse admin panel already has robust analytics data. This is for users that primarily want to track conversions and manage Meta advertisements that help draw users to your forum and to your site.

Features

  • Browser Pixel and server-side Conversions API in one plugin, sharing one event ID so Meta deduplicates instead of double counting
  • PageView, ViewContent, Search, TopicEngaged, CompleteRegistration, TopicCreated, ReplyCreated
  • Fires per SPA navigation, not per page load
  • Server-side conversions still arrive when the browser Pixel is blocked
  • Private messages, restricted categories and admin routes produce no event
  • UGC titles and search text are never sent
  • Staff traffic excludable by group, enforced on server events too
  • Batched delivery with retry classification, rate-limit backoff and a durable idempotency table
  • Diagnostics page showing recent deliveries and their status

Configuration

1. Install

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/multidimension-al/discourse-meta-pixel-capi.git

Then ./launcher rebuild app. The rebuild runs a migration that creates the delivery table.

2. Pixel. Admin → Settings → Meta Pixel & Conversions API. Put your Pixel ID in meta pixel dataset id, then turn on discourse meta pixel enabled. That’s a working Pixel-only setup.

(Meta calls this the Pixel ID in Events Manager and the dataset ID in the Conversions API docs. Same number.)

3. Conversions API (optional). Generate a token in Events Manager → your dataset → Settings → Conversions API. Put it in meta pixel capi access token, then turn on meta pixel capi enabled. The setting refuses to enable without a token and dataset ID.

4. Verify. Put a code from Events Manager → Test Events into meta pixel test event code and browse the forum. Each event should arrive once, not twice. That’s deduplication working. Clear the field afterwards, since events sent with a test code don’t count as conversions.

5. Check. Admin → Plugins → Meta Pixel → Diagnostics shows configuration, browser state, delivery counts and the last 25 deliveries with any errors.

Settings

Name Description
discourse meta pixel enabled Enable the plugin. Off by default.
meta pixel pixel enabled Load the Meta Pixel in the browser.
meta pixel dataset id Your Meta Pixel ID (called the dataset ID in the CAPI docs).
meta pixel capi enabled Send a server-side copy through the Conversions API. Requires a token. Off by default.
meta pixel capi access token Conversions API token from Events Manager. Server-side secret, never sent to the browser.
meta pixel graph api version Graph API version for CAPI requests. Default v26.0.
meta pixel test event code Test Events code. Only set while verifying, since these don’t count as conversions.
meta pixel track page view Send PageView for eligible pages.
meta pixel track view content Send ViewContent when a publicly visible topic is opened.
meta pixel track search Send Search when a full-page search runs. The search text is never forwarded. Off by default.
meta pixel track topic engaged Send TopicEngaged after meaningful reading.
meta pixel topic engaged seconds Seconds of active reading before TopicEngaged fires. Default 30.
meta pixel track complete registration Send CompleteRegistration when an account is created.
meta pixel track topic created Send TopicCreated for a new public topic.
meta pixel track reply created Send ReplyCreated for a reply to a public topic.
meta pixel enhanced email matching Include a SHA-256 hash of the member’s email to improve match quality. Off by default.
meta pixel external id matching Include an opaque HMAC of the user ID. Never a username or email.
meta pixel excluded groups Members of these groups produce no Meta events at all. Default: admins, moderators.
meta pixel respect do not track Send nothing for visitors whose browser reports Do Not Track.
meta pixel public content only Only send content events for topics an anonymous visitor could read.
meta pixel batch size Conversions per request. Meta accepts up to 1000. Default 100.
meta pixel batch max wait seconds How long a partly-filled batch waits. Default 300.
meta pixel delivery retention days Days to keep delivery records. Minimum 7, default 30.
meta pixel debug mode Log dispatched events to the browser console.

Notes

  • Browser and server copies of an event share one ID. Meta deduplicates on event name plus ID within 48 hours, which is why the batch wait window is minutes rather than hours.
  • Topic and reply creation are server-only. A browser copy would add no identity signal, and a client that could assert “a topic was created” could assert it falsely.
  • Registration is sent from the server but paired with a browser event, because at account creation there’s no request in flight to take an IP, user agent or _fbp from.
  • Excluded groups are enforced on every server dispatch path, not just in the browser. TopicCreated, ReplyCreated and CompleteRegistration never involve a browser at all.
  • The endpoint the browser posts to is not a CAPI proxy. It accepts four event names, an event ID, and optionally a topic ID and path. Not a URL, not arbitrary user_data.

There’s a companion Google Analytics 4 plugin built the same way.