What Discord offers, and what it does not
Discord has no tracking pixel, no tag to paste into a page and no conversions API that an advertiser could call. There is nowhere to install one: a server is not a website, and the join happens inside Discord's app or web client, which you do not control. Server Insights on larger community servers shows joins over time and broad source groups, but it is a report inside Discord, not a signal to an ad platform.
So "where do I put the Discord pixel?" has no answer, and the useful question is a different one: how does a join inside Discord get back to the ad that paid for it, with enough identifiers for Meta or TikTok to credit the right click?
Why a pixel on the landing page sees only the click
The common workaround is a landing page with a Meta or TikTok pixel and a "Join the server" button. The pixel fires a page view on load and, if you wire it, a custom event on the button. Then the visitor leaves for Discord and the pixel's part is over. It never learns whether the person pressed Authorise or Cancel, whether they were already a member, or whether they left again the same evening.
The campaign is then optimised for the button press. Meta looks for more people who press buttons, a different group from people who join and stay, and the cost per real member drifts upwards while the cost per button press looks healthy. On a phone the button opens the Discord app and the browser tab is left behind. This is the point where a media buyer asks "is it actually working?" and the pixel cannot say.
The replacement, piece by piece
A pixel bundles three jobs: it recognises the ad click, it observes the conversion and it reports the two together. Without a pixel each job moves to a server.
| Job | What a pixel would need | What is used instead |
| Recognise the click | A page where it can read fbclid and set a cookie | A tracking link of the kind "Opens your Discord server": the redirect records the click with its platform click id, campaign parameters, IP address and user agent |
| Observe the join | A confirmation page inside Discord, which does not exist | Discord's OAuth authorise step: your own application adds the person to the server, so the join passes through your server |
| Tie join to click | A cookie surviving the hand-over to an app | The click id travels in the signed state of the authorise request and comes back with the callback |
| Report it | A browser request from the visitor's device | The delivery worker posts the join to the platform's conversions API with the click's identifiers and a stable event id |
None of this runs on the visitor's device after the first tap, so ad blockers, tracking prevention and the app hand-over stop mattering.
What the authorised join records
The tracking link sends the visitor to Discord's own authorise screen for your application. It asks for two things, "know your username" and "join servers for you", and the second is what lets your application add the person to the server. Someone who authorised before skips the screen; someone not logged in logs in first. Either way the click id is in the request and returns with Discord's answer.
- A new member is recorded as one join, matched to the one click that produced it, and the channel you chose opens in Discord. No invite counter is compared and nobody guesses who used which link.
- Someone already in the server is not counted as a join; authorising twice through the same link is still one member.
- Cancel on the authorise screen still lets the visitor in through a plain invite, but that join is unattributed: it appears in your member count and nowhere else.
- The click alone is kept as a click, so the Dashboard shows how many taps ended in a join; clicks flowing with no joins behind them is one of the checks on the Tracking health page.
No bot process is needed. Your application's bot user sits in the server with the Create Instant Invite permission; no gateway connection and no privileged intents are involved. The walkthrough is in Discord ads tracking setup, and Discord invite tracking explains why this is more exact than an invite-tracker bot.
Retained and Leave for Discord members
A join is the first signal, not the one you buy ads for. On Connections you choose after how many days a member counts as retained; the same number applies to Telegram groups and Discord servers. When a tracked Discord member reaches that age, the worker asks Discord's API whether the person is still in the server. Still there becomes a Retained event on the same click; gone becomes a Leave. Each member is judged once; if Discord does not answer, the row waits for the next hourly pass rather than being guessed.
Retained is sent to Meta and Reddit as a custom event, so a campaign can be judged on members who stayed rather than members who arrived. TikTok, Snapchat and Spotify have no standard event for it and do not receive it. Leave is never sent anywhere: it is kept in your reports so that the Dashboard shows cost per retained member beside cost per join once spend is imported from Meta or Google, and a creative that fills the server with people who leave in a week is visible as such.
This is what "track members, not clicks" means for a Discord server: not the join, but the member still there after the days you chose.
What is sent to the ad platform, and what never is
Removing the pixel does not remove the platform's need to recognise the person. A server event is matched on what the click carried, so a Discord join reaches Meta with:
- the
fbc value rebuilt from the fbclid on the ad click, which is the most direct link to that click;
- the
fbp browser id, only when a Meta pixel on a page the visitor passed through had set its cookie and tracker.js picked it up;
- the IP address and user agent recorded at the redirect;
- your campaign parameters, the event name and time, and a stable event id for deduplication.
Nothing obtained from Discord is sent. Discord's developer policy forbids passing data from its API to advertising networks, and the join is built so that it cannot: the person's Discord id, username, avatar and email never leave Tellmetric, and the id is kept only long enough to run the still-a-member check. The same holds for Retained. That is a narrower set of identifiers than a Telegram join carries, where a hashed Telegram user id serves as an external id, so Meta's match quality for Discord joins can be a little lower. Every attributed join still has the click id, which Meta matches on most reliably; the match-quality panel on Pro and Agency shows what each event carried.
The join goes to Meta on every plan as CompleteRegistration. On Pro and Agency it also goes to TikTok, Snapchat, Reddit, Spotify and X under each platform's matching event name; Google Ads receives the purchases that follow, not the join.
With a landing page or without one
For Meta, TikTok and the other platforms that put a click id in the URL, the ad can point straight at the tracking link; no page is involved. Google Ads is the exception: Google traffic has to land on a page of your own.
If you keep a landing page, the pixel on it stays useful for page-level events, and tracker.js adds what the pixel cannot: it records the visit, keeps the click id in a first-party fbc cookie even when no pixel is present, reads the fbp cookie if a pixel set one, and writes all of it onto every tracking link on the page, including the one that opens your Discord server. Page events then come from the browser and the join, Retained and later purchases from the server, so there is nothing to deduplicate unless you fire the same conversion from both places; the event API accepts your own event id for that case.
Servers sold through Whop
A Whop-gated server adds a purchase to the chain, and Whop's own ads reporting shows spend rather than which member came from which ad. The join is tracked exactly as above; the checkout arrives as a postback with the click id and is reported to Meta as a Purchase with its value. tracker.js also reads Whop's first-party visitor cookie on your landing page and stores it with the click. Whop Discord ads tracking covers that funnel end to end.
Illustrative example
The figures are illustrative. A trading community runs Meta ads to a landing page with a pixel and a "Join" button. Ads Manager reports 600 button presses a week and the server grows by about 250 members, with no way to say which creative the stayers came from. After the button becomes an authorised join link, Meta receives 240 joins and, fourteen days later, 150 Retained events, each tied to its ad. One of three creatives produces members who leave within the week; its budget moves to the other two, and cost per retained member falls while cost per click barely changes.
Frequently asked
Is there a Discord pixel or a Discord conversions API?
No. Discord offers neither a tag for a web page nor a server-side API for advertisers. Attribution has to come from the join itself, which an authorised join link routes through your own application.
Does Meta accept a Discord join as a conversion?
Yes. It arrives as a standard Conversions API event, CompleteRegistration by default, with the fbc value from the ad click, the IP address and user agent, and an event id. Meta shows it in its conversion columns and can optimise for it.
Does the member see anything unusual?
One authorise screen from Discord, once per application, asking to know their username and to join servers for them. Someone who pressed Cancel still gets into the server through a plain invite, unattributed.
What happens if the person leaves?
After the days you set, the worker finds the member gone and records a Leave on the same click. It is never sent to an ad platform; it shows in your reports so cost per retained member reflects it.
Can I run this without a website at all?
Yes for Meta, TikTok, Snapchat, Reddit, Spotify and X: the ad points at the tracking link. Google Ads needs a page of your own, where tracker.js records the visit and fills the Discord link.