> ## Documentation Index
> Fetch the complete documentation index at: https://docs.headlesslabs.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Link Guard & Vanity

> Configure invitation and link detection, invite tracking, and Vanity Status rewards with their actual limits.

This page covers three separate flows under the Vanity module: detecting unapproved invitations and links, attributing new-member invites, and assigning roles tied to an invitation code in a Discord status. It is not a general vanity-role system.

> **Review setup first**
>
> `.vanity quick` enables the detector and tracker, may change `log` to `delete`, and selects an announcement channel. It is not a test mode.

> **Independent tracker**
>
> The tracker attributes joins when it can compare cached invite-use counts. Turning off its announcements does not stop statistics from updating.

> **Actions and limits**
>
> The current Link Guard callback attempts to delete every detected message before applying the selected action, including `log` mode.

## Access and scope

Configuration commands run in a server and require native `Administrator` or the compatible virtual authorization Headless applies to that check. The `/vanity` slash command only toggles the detector; the other configuration groups described here are prefix commands. Detector, allowlist, tracker, and reward settings are scoped separately to each server.

## Link Guard

The detector checks Discord invitations and links in messages. The server's official vanity invite code is allowed automatically; allowlists add exceptions. You can allow an invite/code, URL or domain, subdomain wildcard, path, or one of the `discord`, `youtube`, and `roblox` categories. Paths match the configured path prefix, and a domain rule also matches its subdomains. Up to 120 link rules and 80 exempt roles are stored. An exempt role prevents its members from triggering the detector; it does not grant moderation permissions.

Available actions are `log`, `delete`, `warn`, `timeout`, `kick`, and `ban`. Timeout duration is limited to 1–10,080 minutes. Headless logs matches and, on the active detection path, attempts to delete every blocked message in every mode before running the response. Therefore, `log` does not guarantee that the message remains: the code also posts a notice after the delete attempt. If Discord rejects deletion or a sanction, the operation may be partial; sanction failures are sent to Logs.

> [!WARNING]
>
> If you need to observe links without deleting messages, do not enable the detector assuming `log` is passive. The current implementation attempts to delete detected messages even in `log` mode; review the server policy and test in a dedicated channel first.

> **Detector commands**
>
> * **Status** — **Command:** `.vanity` · **Effect:** Shows detector state, action, timeout, allowed invites/links, and tracker state.
> * **Enable / pause** — **Command:** `.vanity on` · `.vanity off` · `/vanity enabled:true|false` · **Effect:** Changes the detector flag; does not enable or disable the tracker.
> * **Quick setup** — **Command:** `.vanity quick [#channel]` · **Effect:** Enables the module, detector, and tracker; selects a channel; attempts invite synchronization; and changes `log` to `delete` if `log` was the saved action.
> * **Response** — **Command:** `.vanity action ACTION` · **Effect:** `ACTION` must be `log`, `delete`, `warn`, `timeout`, `kick`, or `ban`.
> * **Duration** — **Command:** `.vanity timeout <minutes>` · **Effect:** Saves a timeout from 1 to 10,080 minutes; default is 10.
> * **Invites** — **Command:** `.vanity allow <invite>` · `.vanity disallow <invite>` · **Effect:** Adds or removes an invite code/URL from the allowlist.
> * **Links** — **Command:** `.vanity allowlink <domain or URL>` · `.vanity disallowlink <domain or URL>` · **Effect:** Adds or removes a rule; at most 120 entries are stored.
> * **Role bypass** — **Command:** `.vanity role @Role` · `.vanity unrole @Role` · **Effect:** Adds or removes exempt roles; at most 80 are stored.
>
> The group also accepts `.vn`, `.v`, `.van`, and `.inviteguard`. `quick` turns controls on directly; it does not ask for confirmation or test the trigger. The delete attempt can occur before a timeout, kick, or ban action fails.

> **What happens when a message is posted**
>
> Headless detects invitations and links, normalizes each match, and checks codes, domains/paths, and exempt roles against the server configuration. If there are no blocked matches, it does nothing. Otherwise it creates a `vanity_detected` event with part of the message and selected action, attempts to send it to Logs, attempts to delete the message, and then applies the response. An allowed match does not allow every other link in the same message; each match must pass its own rule.

## Invite Tracker

The tracker is independent from link filtering. When a member joins, Headless compares the available invite-use counts with the previous cache. If it can identify the code and inviter, it updates per-server statistics by inviter and code; if attribution fails, the join is unknown or is not added to an inviter. It cannot reconstruct activity from before tracking began.

`.vanity tracker sync` rereads and caches current invitations; the bot needs `Manage Server` to query invites. It does not import historical joins. `announce off` only stops tracker welcome messages: statistics can continue to update. If the configured channel is unavailable, the runtime may fall back to the general Logs channel.

> **Configure and inspect the tracker**
>
> * **View status** — **Command:** `.vanity tracker` · **Note:** Shows destination, format, and a statistics summary.
> * **Enable / pause** — **Command:** `.vanity tracker on` · `.vanity tracker off` · **Note:** `on` also enables the Vanity module; `off` does not disable Link Guard.
> * **Choose a channel** — **Command:** `.vanity tracker channel [#channel]` · **Note:** Without a channel, uses the current channel if it is a text channel.
> * **Announcements** — **Command:** `.vanity tracker announce STATE` · **Note:** `STATE` accepts `on` or `off`; disables only posting, not attribution.
> * **Format** — **Command:** `.vanity tracker format FORMAT` · **Note:** `FORMAT` accepts `embed` or `text` and selects the join message format.
> * **Template** — **Command:** `.vanity tracker template [text]` · **Note:** Variables: `{member}`, `{member_name}`, `{inviter}`, `{inviter_name}`, `{invite}`, `{joins}`, and `{server}`. Template is limited to 450 characters.
> * **Synchronize** — **Command:** `.vanity tracker sync` · **Note:** Requires the bot to have `Manage Server` to read current invitations.
> * **Statistics** — **Command:** `.vanity tracker stats [@member]` · **Note:** Without a member, shows up to 10 inviters; with a member, shows joins and up to eight codes.
>
> Tracker configuration commands require the same administrator access as the `.vanity` group.

## Vanity Status reward

This reward watches the custom Discord presence, not messages containing invitations. Control it with `.vanity promo status on|off`; `statuscode <code>` and `removestatuscode <code>` maintain up to 20 codes. Headless can assign up to 20 roles configured with `.vanity promo role @Role`. The bot needs the privileged Presence intent enabled in the Discord application, a member available in the gateway state, `Manage Roles`, and a role position high enough to assign the configured roles. `.vanity promo statuschannel #channel` selects the panel destination; `.vanity promo scan` checks only members currently cached by the server.

`.vanity promo statusremove on|off` controls removal when the status code disappears; the delay accepts 0–604,800 seconds. Removal is best effort: if Discord rejects a role removal, the stored assignment can stop reflecting reality while the member still has the role. Periodically verify hierarchy and existing roles.

**Note:**

`.vanity promo on|off` controls the status panel/announcements, while `.vanity promo status on|off` controls the role reward. These are separate toggles. The panel also supports a template, title, ping text (without active mentions), thumbnail, banner, and GIF.

> [!NOTE]
>
> Automatic promotion when a member posts an invite is configured in the `.vanity promo` group, but its message callback is not connected in the reviewed runtime. Do not treat it as an active feature. The implemented reward is the Vanity Status reward.

## Steps

**1. Review the current action and permissions**

Run `.vanity` and verify the bot's permissions. Do not use `quick` as a test: it enables both the detector and tracker and may change `log` to `delete`.

**2. Keep exceptions narrow**

Allow only the invites, domains/paths, and roles that should be exempt. Test each allowed URL with a server test case.

**3. Decide whether to enable the detector**

Because the callback attempts message deletion even in `log` mode, enable it only when that behavior is approved. Select an explicit action and monitor Logs.

**4. Configure the tracker or reward separately**

Synchronize invites for the tracker. For status rewards, enable Presence intent, validate role hierarchy, and configure roles and status channel separately.

## Commands by workflow

### Invite, link, and role allowlists

```headless-command Syntax theme={null}
.vanity allow <invite>
```

```headless-command Example theme={null}
.vanity allow a1B2c3
```

```headless-command Syntax theme={null}
.vanity allowlink <item>
```

```headless-command Example theme={null}
.vanity allowlink roblox.com
```

```headless-command Syntax theme={null}
.vanity role <role>
```

```headless-command Example theme={null}
.vanity role @Trusted
```

### Invite attribution and statistics

```headless-command Syntax theme={null}
.vanity tracker sync
```

```headless-command Example theme={null}
.vanity tracker sync
```

```headless-command Syntax theme={null}
.vanity tracker channel [channel]
```

```headless-command Example theme={null}
.vanity tracker channel #invites
```

```headless-command Syntax theme={null}
.vanity tracker stats [member]
```

```headless-command Example theme={null}
.vanity tracker stats @Inviter
```

### Vanity status reward

#### `.vanity promo status`

```headless-command Syntax theme={null}
.vanity promo status <state>
```

```headless-command Example theme={null}
.vanity promo status on
```

#### `.vanity promo statuscode`

```headless-command Syntax theme={null}
.vanity promo statuscode <code>
```

```headless-command Example theme={null}
.vanity promo statuscode verified
```

#### `.vanity promo role`

```headless-command Syntax theme={null}
.vanity promo role <role>
```

```headless-command Example theme={null}
.vanity promo role @VerifiedMember
```

#### `.vanity promo statuschannel`

```headless-command Syntax theme={null}
.vanity promo statuschannel <channel>
```

```headless-command Example theme={null}
.vanity promo statuschannel #vanity-status
```

## Related pages

* [Honeyspot](/docs/en/security/honeyspot.md)
* [Logging](/docs/en/server/logging.md)
* [Roles](/docs/en/server/roles.md)
* [Headless Permissions](/docs/en/permissions.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.