Administrator reviewing a forum thread list beside a muted chat sidebar on a dual-monitor desk

XenForo does not ship Discord. Setup → Connected accounts lists Apple, Facebook, Google, Twitter/X, GitHub, Microsoft, LinkedIn and friends. Official 2.3 does name Discord as a place webhooks can notify. That is the honest split: stock XenForo can tell Discord that a thread was posted. It cannot log someone in with a Discord account, cannot push a Whitelisted group to a guild role, and cannot make Discord the sidebar chat. Those jobs are add-ons — or they are a sentence in the landing page that says “we also have a Discord” and a link.

This is not “forum vs Discord.” That comparison is a later topic. This is the integration: pick one job, ship it, measure it. A board that requires Discord login, syncs every group to a role, mirrors every post, and embeds a widget on the first screen has four products and one outage.

Official sources: XenForo connected-accounts manual, 2.3 OAuth2 and webhook notes in the official-docs notebook, Discord’s own incoming-webhook docs. Community: the long-running [8WR] Discord Integration resource (Jaxel, current 2.3.0.x, listed compatible with XF 2.3) and the 2.3 webhooks thread where people route events through Make / Zapier / n8n.

Four jobs, four tools

Job Stock 2.3? Typical extra
Announce new public threads in a Discord channel Almost. Setup → Webhooks can fire thread_insert. Discord wants its own JSON, so you usually need a formatter Make / Zapier / n8n, or an add-on that posts Discord-shaped messages
Log in / register with Discord No. Discord is not a stock connected-account provider A Discord connected account add-on, or [8WR] which includes OAuth2 login
Map XenForo groups to Discord roles; mirror bans; force nicknames No [8WR] Discord Integration (paid). Guild bot + OAuth
Live chat on the forum No Not what [8WR] is. Reviews are explicit: it is not a Discord chat box

If you only need the first row, do not buy the third. If you need the third, you will also get the second, because role sync requires a linked Discord user.

Stock: connected accounts (the pattern Discord will copy)

Official connected-accounts chapter: visitors log in and register through a provider so they do not invent another password. You register an application at the provider, then paste the key and secret into XenForo.

Official test, after any provider:

  1. Setup → Connected accounts
  2. Test provider next to the row
  3. Test

A good test shows name, email, and avatar where the provider sends them. A bad test: fix Board URL first, then the client id / secret. The first time a member uses the provider they must allow the application.

That is the whole stock lesson. Discord is not in the list. When you install a Discord connected-account add-on, you will do the same dance at Discord Developer Portal: create an application, OAuth2 redirect URL that matches your board (including https and any /community/ subdirectory), client id + secret into the add-on, then XenForo’s test button if it offers one. Discord OAuth scopes you actually need for login are small (identify, usually email). Bot scopes (bot, guild members) are a different application use — that is role sync, not login. Do not tick every scope “to be safe.” Discord will show members a scary consent screen and you will collect tokens you do not need.

XenForo 2.3’s OAuth2 server (/api/oauth2/authorize, /api/oauth2/token, /api/oauth2/revoke) is the opposite direction: XenForo is the identity provider for WordPress or another app. Official notebook: confidential clients (server-side secret) vs public clients (PKCE). That is not “log in with Discord.” Do not confuse the two.

Stock: webhooks to Discord

Official 2.3: Setup → Webhooks. You set a URL and pick events. Documented examples: thread_insert, user_register. Outgoing requests are signed with XF-Webhook-Secret so the receiver can check the origin. Payload can be JSON or url-encoded. Official materials name Discord and Slack as the chat platforms this is for.

Discord incoming webhooks (Discord support: Server settings → Integrations → Create webhook, pick a channel, copy the URL) accept Discord’s own body: typically content and optional embeds. They do not speak XenForo event JSON. Community 2.3 threads therefore put Make, Zapier, IFTTT, or n8n between the two: XF posts the event → the scenario maps thread.title / URL into content → Discord posts.

That stack is enough for “new public thread in Announcements.” It is not role sync. It will also fire for threads guests cannot see if you pointed it at a private node — filter in the scenario, or only attach the webhook to events you would print on a billboard.

Do not paste a Discord webhook URL into XenForo and assume a pretty embed. Test with a dummy thread. If Discord returns 400, the body is wrong, not “webhooks are broken.”

Keep the secret and the Discord webhook URL in the same drawer as config.php. Anyone with the Discord URL can spam that channel until you rotate it.

When you actually need [8WR]

[8WR] Discord Integration (Jaxel, resource 6058, 2.3.0.4 listed for XF 2.0–2.3, paid, branding removable for extra money) is the add-on people mean when they say “Discord integration” on XenForo Community. Advertised jobs, from the resource page:

  • Register / login on XenForo through Discord OAuth2
  • Assign Discord roles from XenForo user groups
  • Enforce username matching XenForo → guild
  • Enforce bans: banned on the forum → banned on the guild
  • Post new threads, replies, and status updates to guild channels

Author notes in the discussion: accounts sync one by one, default about one a minute — so a 2,000-member link night is a long night, not an instant. Reviews (read them as operations, not as stars):

  • It is good at telling Discord a post happened and at roleplay boards that want roles to match groups.
  • It is not a chat widget. A 2024 review is blunt: if you wanted Discord in the forum as chat, this is not it.
  • Setup wants the author’s video and the add-on permissions (community mentions a Link Discord account permission). ThemeHouse / custom styles have broken the navbar item for some people.
  • Support reputation is mixed. Budget time to read the FAQ, not a same-day Slack from the author.

Install it when you have a guild you already moderate and a XenForo group map you already trust — Whitelisted, Subscriber, Moderating. Do not invent twenty Discord roles to match twenty leftover XF groups. The ranks article just told you cosmetic groups are expensive. Syncing them to Discord makes them expensive twice.

A lighter alternative if you only want login: a Discord connected-account provider add-on (open-source examples exist on GitHub; treat any named third-party as something you verify against XF 2.3 today). Login only. No bot. No role sync. Members still type a Discord invite by hand.

Discord Developer Portal, without the folklore

For login (any CA add-on):

  1. Create an application.
  2. OAuth2 → add redirect. The URL the add-on documents — usually something under your board — must match character for character, including trailing slash policy.
  3. Copy client id / secret into XenForo or the add-on.
  4. Test. Then test as a second Discord account that is not yours.

For role sync / bans / nicknames you also need a bot:

  1. Bot token lives on the server, never in a public template, never in an HTML widget.
  2. Invite the bot with the minimum guild permissions: manage roles (below the bot’s highest role), maybe kick/ban if you really want XF bans to land in Discord. A bot with Administrator is how a leaked token is a guild-wipe.
  3. Role hierarchy: the bot can only assign roles below itself. Put the synced roles under the bot. Do not try to assign @everyone or a role above the bot.

Username matching: decide whether Discord nicks should become the forum name or the other way around. Gaming boards usually want the forum name on Discord so staff can search one string. Enforce that only after people have linked. A surprise nick-change on join is how you get a #support pile.

What not to do

Do not require Discord to register. Official connected accounts are a reduction of friction. A required Discord login excludes people who will not give a chat platform their email, and it makes your forum a hostage of Discord’s outage. Keep stock registration. Offer Discord as optional. The whitelist already said: Discord handle as a field on the application, not as the account.

Do not embed a Discord widget on the LCP screen. The performance article is the reason. A text invite on the landing page is enough.

Do not sync Staff / Admin groups until you have Protected-style rules in Discord. A junior node mod who can grant the XenForo Moderating group should not be able to grant Discord Administrator through a sync map. Map down, never up.

Do not announce private nodes. Webhook + thread_insert does not know your feelings. It knows the event. Attach it to public rooms, or filter.

Do not treat Discord as the archive. Threads on XenForo are the record. Discord is the pager. When someone asks “what did we decide,” the answer is a thread, not a scrollback.

A sane first month

Week 1: public Discord invite on the landing page and in an HTML widget. No add-on. See if anyone uses it.

Week 2: Setup → Webhooks → formatter → one #forum-feed channel for one public forum (announcements). Watch noise.

Week 3: if members actually ask to log in with Discord, install a CA provider or [8WR] and turn only OAuth login on. Permission: who may link. Test provider / test user.

Week 4: if you have a group that already means something (Whitelisted, Subscriber), map that one group to one Discord role. Leave bans and nickname enforce off until the map has been correct for a week.

Redirect URLs and email collisions

Official connected-account tests fail most often on Board URL. Discord is worse because the Developer Portal stores an exact redirect list. Typical add-on callbacks look like /connected_account.php?provider=discord or a rewritten /connected_account/discord. Copy the URL from the add-on readme, then from a failed test’s query string, not from memory. http vs https, www vs apex, and a /community/ subdirectory each count as a different app.

If a member already has a XenForo account with sam@example.com and then clicks “Log in with Discord” on an address Discord also has, stock connected accounts try to associate. If the emails differ, you get a second XF account. Write that in the onboarding FAQ: link Discord from Account → Connected accounts while already logged in. Do not invent a merge tool this article cannot cite.

Privacy: you are sending members through Discord’s OAuth consent. Say so. Do not store a bot token in an HTML widget, a public Git repo, or a staff thread guests can guess. Rotate the Discord webhook if a moderator leaves.

What a formatter actually sends

XenForo’s webhook body is an event. Discord’s incoming webhook wants roughly:

{
  "username": "Forum",
  "content": "New thread: Example title\nhttps://example.com/threads/example.123/"
}

Make / n8n: filter discussion_state / node id if the payload has them, skip anything you would not show a guest, then map title + link. If the scenario cannot see a public URL, you are not ready to automate.

[8WR] skips this hop for the events it already posts. That is the product. It still will not turn Discord into the moderation queue.

Staff load is the hidden cost

Every synced role is a second place a permission mistake is visible. Every #forum-feed of replies is a second timeline members will ask you to “moderate.” Official large-forum practice still applies: node mods on XenForo do not automatically become Discord mods. Write who owns the guild. If the answer is “whoever has the bot,” you do not have an integration. You have a token.

When Discord is down, the forum must still register, post, and approve applications. That is why Discord is optional in week 1. A board that only exists as a Discord login button is not a XenForo community. It is a waiting room.

Checklist

  • Written job: announce / login / roles / (not chat)
  • Board URL correct before any OAuth test
  • Stock registration still works without Discord
  • If webhooks: Setup → Webhooks, secret stored, events limited, formatter tested, private nodes excluded
  • If login: Discord application, redirect URL exact, minimum scopes, second-account test
  • If [8WR]: 2.3 build, Link Discord account permission decided, sync rate accepted, not used as a chat box
  • Bot token not in templates; bot role above only the roles it must assign
  • No Discord iframe on the homepage
  • Staff handbook: Discord is the pager, the forum is the record

A good Discord integration is a linked optional account and a quiet #forum-feed. Everything else is a second community you now have to moderate. Staff that already, using the large-forum shift, before you sync another group.

A worked #forum-feed without [8WR]

You have one public announcements forum and a Discord channel nobody uses for chat. Goal: a guest-safe line when a new thread is visible.

  1. Discord: Server settings → Integrations → Webhooks → New webhook. Name it Forum. Channel #forum-feed. Copy the URL. Treat it like a password.
  2. XenForo: Setup → Webhooks → add a URL that is not the Discord URL — it is your Make/n8n catch hook. Event: thread_insert only.
  3. In the scenario: if the payload has a node id / name, allow-list announcements. If you cannot see visibility, do not go live. Map title + public thread URL into Discord content. Post.
  4. Create a dummy thread as a guest-visible account. Confirm the Discord line. Soft-delete the dummy. Confirm you do not also fire on a thread in a private node (create one; it must stay silent).
  5. Write the XF-Webhook-Secret check into the scenario if the tool supports header verification. Official header name is XF-Webhook-Secret.

That is a finished integration. It took an afternoon. It does not sync roles.

Common [8WR] failures (from reviews and the resource thread)

  • “There is no valid…” on connect. Redirect URL or Board URL. Test with a second Discord account, not the bot owner only.
  • Roles not syncing. Bot role is below the roles it must assign, or the XF group is not in the map, or you expected instant: default is about one account a minute.
  • Navbar item missing. Custom style. The add-on is not a chat box; a 2024 review bought it for that and said so. Put a text link in an HTML widget instead of fighting PAGE_CONTAINER.
  • ThemeHouse / extra JS. 2.3 already deferred modules. An old 2.1 leftover plus minified-JS changelog (2.3.0.4) is a reminder: do not run fullJs on production while you debug this.
  • Support. Read the FAQ video first. Budget a weekend, not a same-day ticket.

If login is the only job, a dedicated Discord connected-account provider is less bot surface than [8WR]. If roles are the job, [8WR] is still the named 2.3-compatible product on the resource manager. Verify the build number on the day you buy.

Data you are now holding

A linked Discord user id is personal data. A bot token is a guild key. A webhook URL is a spam cannon. Put them in the same ops note as config.php: who can see them, how you rotate them when a staffer leaves, whether you delete the Discord link when you delete the XF account. Official XenForo will not do that last step for a third-party provider unless the add-on does.

Do not scrape Discord member lists into a public widget. Do not put Discord avatars on the portal first screen. The performance article is not optional because the logo is pretty.