---
title: Audience Gating
description: "Restrict documentation pages to specific client audiences"
---

# Audience Gating

Audience gating lets you control which documentation pages are visible to different client segments. This is essential for B2B platforms that serve multiple clients with different product access levels.

<Callout type="info">
  Audience gating is available on **Pro** and **Enterprise** plans.
</Callout>

## Overview

With audience gating, you can:

- Tag pages with audience requirements (e.g., `enterprise`, `beta`, `otc`)
- Create audience profiles for clients/partners
- Generate access tokens that unlock gated content
- Share magic links for frictionless client access

Pages without audience tags remain public and visible to everyone.

## Hidden by Default

Gated content is **invisible** to visitors without a matching access token — not just blocked. Until a valid token is presented, a gated page:

- Does **not** appear in the sidebar navigation or previous/next page links
- Does **not** appear in search results
- Is **never** used by the AI assistant when answering questions
- Is excluded from `llms.txt`, `llms-full.txt`, and `sitemap.xml`
- Cannot be fetched as raw Markdown (`.md` exports are gated too)

The same applies to `<AudienceGate>` sections inside public pages — gated sections are stripped from the HTML at the edge and excluded from search indexing and AI retrieval.

The only way an unauthorized visitor encounters a gated page is by opening its URL directly — in that case they see an access modal where they can enter an access code.

## How It Works

```mermaid
flowchart LR
    A[Page Request] --> B{Gated Page?}
    B -->|No| C[Serve Page]
    B -->|Yes| D{Has Token?}
    D -->|No| E[Show Gate Page]
    D -->|Yes| F{Valid Token?}
    F -->|No| E
    F -->|Yes| G{Audience Match?}
    G -->|No| E
    G -->|Yes| C
```

1. **Tag pages** — Add `audience` to page frontmatter
2. **Create profiles** — Define audience profiles for each client
3. **Generate tokens** — Create access tokens per profile
4. **Share access** — Send magic links or raw tokens to clients

## Tagging Pages

Add the `audience` field to any page's frontmatter to restrict access:

```yaml
---
title: OTC Trading API
description: Execute over-the-counter trades
audience: [otc]
---
```

### Audience Tag Rules

| Configuration | Behavior |
|---------------|----------|
| No `audience` field | Page is public (visible to everyone) |
| `audience: []` | Page is public (empty array = no restrictions) |
| `audience: [tag]` | Page requires the specified tag |
| `audience: [tag1, tag2]` | Page visible if client has **any** matching tag |

### Example: Multi-Product Docs

```yaml
# docs/guides/transfers.mdx
---
title: Transfers Guide
audience: [transfers]
---
```

```yaml
# docs/guides/otc-trading.mdx
---
title: OTC Trading Guide
audience: [otc]
---
```

```yaml
# docs/guides/advanced-setup.mdx
# Only for enterprise customers
---
title: Advanced Setup
audience: [enterprise]
---
```

```yaml
# docs/getting-started.mdx
# No audience field = public page
---
title: Getting Started
---
```

## Gating Sections Within a Page

Use the `<AudienceGate>` component to restrict a section of an otherwise public page. The section is stripped at the edge for visitors without a matching audience tag — the rest of the page stays fully accessible:

```mdx
## Rate Limits

Standard plans allow 100 requests per minute.

<AudienceGate audience="enterprise">

### Custom Rate Limits

Enterprise plans support custom rate limits. Contact your account manager.

</AudienceGate>
```

Multiple tags are supported (`audience="beta, enterprise"`) — the section is visible if the visitor has **any** matching tag. Section gating and frontmatter gating can be combined on the same page.

See the [Audience Gate component reference](/components/audience-gate) for full details.

## Managing Audience Profiles

Audience profiles are managed in the dashboard or via the API.

### Dashboard Setup

1. Go to **Settings → Audience Gating**
2. Click **Create Profile**
3. Enter profile details:
   - **Name** — Display name (e.g., "Acme Corp")
   - **Slug** — URL-safe identifier (e.g., `acme-corp`) — immutable after creation
   - **Description** — Optional notes
   - **Audiences** — Tags this profile grants access to

<Image src="/images/audience-profiles.png" alt="Audience Profiles Dashboard" />

### Example Profiles

| Profile | Slug | Audiences |
|---------|------|-----------|
| Acme Corporation | `acme-corp` | `otc`, `virtual-accounts` |
| Beta Testers | `beta-testers` | `beta` |
| Enterprise Partners | `enterprise` | `enterprise`, `transfers`, `otc`, `cards` |

## Generating Access Tokens

Each profile can generate access tokens that unlock its assigned audiences.

### Via Dashboard

1. Go to **Settings → Audience Gating**
2. Find the profile and click the **key icon**
3. Copy the **Raw Token** or **Magic Link Parameter**

### Via API

```bash
curl -X POST https://api.syntext.dev/internal/projects/:projectId/audience/token \
  -H "Authorization: Bearer stx_abc12345_..." \
  -H "Content-Type: application/json" \
  -d '{"profileSlug": "acme-corp"}'
```

Response:

```json
{
  "token": "eyJwcm9qZWN0SWQiOiIxMjM0NSIsInRpbWVzdGFtcCI...",
  "audiences": ["otc", "virtual-accounts"]
}
```

## Sharing Access

### Magic Links (Recommended)

Magic links provide frictionless access — clients click once, and a cookie is set automatically.

Append `?_stx_token=TOKEN` to any docs URL:

```
https://acme-docs.syntext.dev/guides/otc?_stx_token=eyJwcm9qZWN0SWQ...
```

When the client visits:
1. Token is validated
2. `_stx_audience` cookie is set (30-day TTL)
3. Client is redirected to the clean URL

Subsequent visits to any gated page work without re-entering the token. Once the cookie is set, gated pages also appear in the sidebar navigation and search results, and the AI assistant can use them when answering questions.

### Raw Token

Clients can also paste tokens directly on the gate page:

1. Client visits a gated page without a token
2. Gate page displays with a token input form
3. Client pastes their token
4. Cookie is set and they're redirected to the page

## Gate Page

When visitors lack access to a gated page, they see a styled gate page:

<Image src="/images/gate-page.png" alt="Gate Page Example" />

The gate page:
- Matches your doc site's theme
- Shows which audiences are required
- Provides a token input form
- Displays clear error messages for invalid tokens

## API Consumer Access

For non-browser API consumers, send the token via header:

```bash
curl https://acme-docs.syntext.dev/guides/otc \
  -H "x-audience-token: eyJwcm9qZWN0SWQ..."
```

API consumers receive JSON error responses:

```json
// No token
{ "error": "audience_required", "requiredTags": ["otc"] }

// Invalid token
{ "error": "invalid_audience_token" }

// Wrong audience level
{
  "error": "insufficient_audience",
  "requiredTags": ["otc"],
  "userTags": ["cards"]
}
```

## Build Pipeline Integration

At build time, Syntext:

1. Reads `audience` from each page's frontmatter
2. Generates `_audience.json` — maps page slugs to required tags
3. Uploads the manifest to the CDN
4. Excludes gated pages from `llms.txt`, `llms-full.txt`, and `sitemap.xml`
5. Indexes audience tags alongside search documents and AI embeddings so gated content is only surfaced to authorized visitors

The manifest looks like:

```json
{
  "guides/otc-trading": ["otc"],
  "guides/advanced-setup": ["enterprise"],
  "api/virtual-accounts": ["otc", "virtual-accounts"]
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Use Meaningful Tag Names">
    Choose clear, product-aligned names like `transfers`, `otc`, `enterprise` rather than generic names like `tier1`, `level2`.
  </Card>
  <Card title="Keep Public Pages Public">
    Don't gate getting-started guides or basic concepts. Only restrict product-specific content.
  </Card>
  <Card title="Overlap Audiences">
    A page with `[otc, transfers]` is visible to clients with either tag — use this for shared content.
  </Card>
  <Card title="Rotate Tokens Periodically">
    Generate new tokens periodically and revoke old ones, especially when client relationships change.
  </Card>
</CardGroup>

## Troubleshooting

### Client Can't Access a Gated Page

1. Verify the client's profile has the required audience tag
2. Check that the token hasn't expired
3. Ensure cookies are enabled in their browser
4. Try generating a fresh token and magic link

### Pages Still Visible After Adding Audience Tag

Audience gating is enforced at runtime, but the change requires a rebuild:

1. Commit the frontmatter change
2. Push to trigger a build
3. Wait for the build to complete

### Token Works in Browser but Not API

Ensure you're sending the token in the `x-audience-token` header, not as a cookie.

## Related

- [Audience Profiles API](/api-reference/audiences/list) — Manage profiles via API
- [Configuration Reference](/configuration/frontmatter) — All frontmatter fields
