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

# Middleware

> One edge middleware, shipped by the SDK and re-exported by every site, runs campaign landings, the private-site gate and visit logging in front of every request.

```ts theme={null}
// middleware.ts at the site root
export { default, config } from "@sp-stage/sdk/middleware";
```

It matches everything except API and build asset paths and runs three jobs in order.

## 1. Campaign landing

`?c=<code>` and legacy `/l/<slug>`: resolve, stamp `stage_ref`, `302` to the clean URL. Detail in [Campaign landing](/developers/analytics/campaign-landing).

## 2. Private site gate

When an org is private, every request needs a `stage_access` cookie.

* The cookie is a short-lived signed token (ES256) minted by the API for members and set on the site domain by the admin after sign-in. Seven days, cleared on sign-out.
* The middleware polls a public, CDN-cached endpoint for the org's mode and the public verification key. A flip propagates in about a minute with no redeploy, and the deployment holds no signing material.
* Blocked requests redirect to `/admin?from=<path>`. After sign-in the admin sets the cookie and sends the visitor back.
* Presentation assets (CSS, scripts, fonts, images) are exempt so the admin can draw itself. Content-bearing files (HTML, sitemaps, text, JSON) are gated.
* **Fail-open only when blind.** An unreachable API holds the last cached verdict; with no cache at all the site serves. An outage must not take every site down.

Revocation lags up to the cookie lifetime. Media stays reachable at hashed URLs.

## 3. Visit logging

For a top-level document request: classify the user agent, apply the consent rule, read the session and UTMs, and post the visit to the API's ingest route after the response. Detail in [Tracking](/developers/analytics/tracking).

## Local development

Edge middleware does not run under the dev server. The template's dev-only Astro middleware applies the landing and gate verdicts and is compiled out of static builds, where build-time middleware must never fire.

## Exports a site can use

| Export                                            | Use                                    |
| ------------------------------------------------- | -------------------------------------- |
| `campaignLanding`, `privateGateVerdict`           | The dev middleware calls these         |
| `extractUtm`, `parseRefCookie`, `encodeRefCookie` | Read the attribution a request carries |
| `isRecordableView`                                | Whether a path counts as a page view   |
| `CAMPAIGN_CODE_PARAM`, `REF_COOKIE`               | The reserved names                     |
