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

# Get started

> From an account to a card on a live page: register a site, define a fragment, wire your edge, then prove both request paths behave.

export const Pill = ({variant = "alpha", children}) => <span className={`ds-pill ${variant}`}>{children}</span>;

This is the shortest path to a working integration. It ends with a check that tells you the difference
between *working*, *working with nothing to serve*, and *broken*, which is the part most integrations get
wrong.

## Before you start

Have these four things ready. Every step below assumes them.

| You need                 | Where it comes from                                                                                               |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| A doubleshift account    | [app.shftd2.com](https://app.shftd2.com). Your **account id** is the `partner_id` you will pass on every request. |
| An API key               | **Settings → API keys** in the console. Shown once, so copy it immediately. See [API keys](/api-keys).            |
| Edit access to your edge | Your CDN configuration or your page template. Which one depends on the path you pick below.                       |
| One public test page     | A real, public URL on the site you are about to register. Avoid a page behind a login or a consent wall.          |

## Pick your edge path

The integration lives at your edge, never in a browser. Two paths, decided by your CDN:

| Your CDN                | Path        | What you write                                                                         |
| ----------------------- | ----------- | -------------------------------------------------------------------------------------- |
| Akamai, Fastly, Varnish | **ESI tag** | One tag in the page template, plus a rule that enables ESI for AI-agent requests only. |
| Cloudflare              | **Worker**  | A small Worker in front of the origin that inlines the card.                           |

Both are written out, with their caveats, in [Edge integration](/edge-integration). Read that page when you
get to step 3; this page keeps to the happy path.

<Steps>
  <Step title="Register your site">
    In the console, open [Sites & fragments](https://app.shftd2.com/sites) and add your **bare domain**,
    host only. Protocol and path are stripped, so `https://sillage-mag.fr/news` becomes
    `sillage-mag.fr`. See [Sites](/sites).
  </Step>

  <Step title="Define a fragment">
    Create a fragment on that site: a name, a language, and, if you already know them, the key-values you
    want to accept. Copy the `fragment_id` it gets, in the form `frg_…`. That id goes in the endpoint URL.
    See [Fragments](/fragments).

    Leave the matching policy at its default for now. Tightening it is a [targeting](/targeting) decision,
    not an integration one, and a strict policy makes step 5 harder to read.
  </Step>

  <Step title="Add the edge adapter">
    Take the snippet for your path from [Edge integration](/edge-integration) and replace four values:
    your account id, your `fragment_id`, the language, and your API key.

    The key must stay server-side, rendered in an ESI tag or held in an edge worker. Never put it in
    client-side JavaScript or in a URL a visitor can read.
  </Step>

  <Step title="Gate the call on the agent User-Agent">
    Only AI-agent requests may reach the fragment endpoint. Humans must never trigger it. The agent list
    and the exact gate for your CDN are in [Edge integration](/edge-integration); the canonical markers are
    in the [reference](/reference).
  </Step>

  <Step title="Verify both request paths">
    Against your live test page, run the human path and the agent path:

    ```bash title="Verify both paths" theme={"theme":"css-variables"}
    # As a human, expect no card:
    curl -s https://your-domain.example/some-article | grep -c 'abc-card'

    # As an AI agent, expect one card:
    curl -s -A "Mozilla/5.0 (compatible; GPTBot/1.0)" \
      https://your-domain.example/some-article | grep -c 'abc-card'
    ```

    Read the two numbers together:

    | Human | Agent | What it means                                                                                                   |
    | ----- | ----- | --------------------------------------------------------------------------------------------------------------- |
    | `0`   | `1`   | Working. Humans untouched, agents enriched.                                                                     |
    | `0`   | `0`   | Either no card was eligible for that page, or your gate never fired. Not the same thing, so disambiguate below. |
    | `1`   | `1`   | Your gate is not gating. Humans are getting cards, which is not what you want.                                  |
  </Step>

  <Step title="Disambiguate a double zero">
    Call the endpoint directly, without your edge in the way:

    ```bash title="Ask the endpoint itself" theme={"theme":"css-variables"}
    curl -s -o /dev/null -w '%{http_code}\n' \
      'https://api.shftd2.com/fragment?partner_id=<your account id>&fragment_id=<your fragment id>&lang=<lang>&page_url=https://your-domain.example/some-article' \
      -H 'X-API-Key: <your key>'
    ```

    | Code                                | Where the problem is                                                                                                               |
    | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
    | <Pill variant="code-200">200</Pill> | The endpoint has a card for that page, so the gap is in your edge: the gate, or the inlining.                                      |
    | <Pill variant="code-204">204</Pill> | The integration is fine. Nothing is eligible for that page yet, or the fragment is paused. This is a healthy state, not a failure. |
    | <Pill variant="code-err">401</Pill> | The key is missing, wrong, or revoked.                                                                                             |
    | <Pill variant="code-err">403</Pill> | The key is valid but does not own that `partner_id` or `fragment_id`.                                                              |
    | <Pill variant="code-err">400</Pill> | A required parameter is missing: `partner_id`, `fragment_id` or `lang`.                                                            |
  </Step>
</Steps>

## You are live when

* your site is registered and your fragment is **active**;
* the human path returns no card, on every page;
* the agent path returns a card on a page that has an eligible one;
* a direct call to the endpoint answers <Pill variant="code-200">200</Pill> or <Pill variant="code-204">204</Pill>, never a `4xx`.

## Common symptoms

| Symptom                                                                          | Most likely cause                                                                                                                                                                                   |
| -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Nothing changes for agents, endpoint answers <Pill variant="code-200">200</Pill> | The gate never matches, or the response is inlined after `</body>` and dropped.                                                                                                                     |
| It worked, then stopped                                                          | The key was rotated or revoked, or the fragment was paused. Cached responses stay available for their cache window.                                                                                 |
| The card appears for humans too                                                  | The ESI or Worker path is not gated on the agent `User-Agent`.                                                                                                                                      |
| The include is silently skipped                                                  | Your edge protection is blocking the bot `User-Agent` on the subrequest. Send the real agent in `X-Agent-UA` and keep a benign `User-Agent`, as described in [Edge integration](/edge-integration). |

## Then

<CardGroup cols={2}>
  <Card title="Decide what you accept" icon="sliders-horizontal" href="/targeting">
    Key-values and `match_mode`: how tightly you want serving constrained.
  </Card>

  <Card title="Read the endpoint contract" icon="code" href="/reference">
    Every parameter, every response code, the cache headers and the agent markers.
  </Card>
</CardGroup>
