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

# Page feedback

> Ingest a client's page feedback as structured, verbatim defect observations bound to the page's variant — instead of hand-typing a feedback round into a thread.

# Page feedback

A client feedback round usually arrives as a pile of comments about specific pages — "the hero on
the B variant is confusing", "the pricing page's CTA is broken on mobile". Left as prose in a
thread, that feedback has to be re-read and re-typed into something the loop can act on every time.
**Page feedback** intake skips the retyping: you submit the round as a structured list, one item per
page, and each item lands directly as a **defect observation** on the [experiment](/experiments)
ledger — the same record judge generation and the reconciliation loop already read.

## What an item is

Each item names the page, carries the client's words, and optionally points at an image:

* **`experiment_slug`** — the experiment the page belongs to (its slug, or its id).
* **`variant_key`** — which of that experiment's variants the feedback is about. It must be one of
  the experiment's real variant keys; naming one that doesn't exist fails the item.
* **`feedback`** — the client's own words. This is stored **byte-for-byte as submitted** as the
  defect's reason — intake does no trimming, summarizing, classifying, or rewriting. If
  you want a cleaner or categorized version, produce that yourself before calling; the words you
  submit are the words that land.
* **`image_bucket_key`** *(optional)* — anchors the item to an image (a screenshot of what's wrong),
  uploaded first via the image-upload tool and referenced here by its returned key.

A round is one or more items, and every item is validated — the experiment resolves, the variant is
real, the feedback isn't empty — **before writes begin**. A typo anywhere in the round writes no
observations.

## Where it lands

Every item mints a **`defect`** observation: `variant_key` the flagged variant, `judge_slug`
`human:<you>`, and the feedback text as `reason` — the exact shape and channel [your attention
feed's](/attention) flagged-broken-variant response writes to when you flag a variant broken while
answering a choice. Page feedback intake is a second door into the same room: whether a defect was
raised by picking "flag broken" on a choice you were shown, or submitted directly here by
experiment and variant, judge generation reads it identically — it is collected as a standalone
failure list, seeding the lenses that should have caught it.

Because it is a real experiment observation, it's also visible anywhere observations are:
`erdo_list_experiment_observations`, `GET /v1/experiments/:slug/observations`, and
`erdo experiment observations <slug>` all return it filtered to `observation_type=defect`.

Writing a defect requires contributor access to the page's project — the same bar every surface that
records an observation against an experiment you name directly holds (see [experiments](/experiments)).

## Programmatic access

Page feedback intake is MCP, REST, and CLI — there is no separate UI form; submit a round from
wherever you collect it (a support inbox, a client call transcript, a review tool).

```bash theme={null}
# one item
erdo page-feedback record \
  --experiment homepage-hero-q3 \
  --variant treatment_b \
  --feedback "The hero image is cut off on mobile and the CTA text is barely readable."

# a whole round, from a file or inline JSON
erdo page-feedback record --items @feedback-round.json
erdo page-feedback record --items '[
  {"experiment_slug":"homepage-hero-q3","variant_key":"treatment_b","feedback":"Hero image cut off on mobile."},
  {"experiment_slug":"pricing-page-q3","variant_key":"control","feedback":"Annual/monthly toggle does nothing."}
]'
```

### MCP tools

| Tool                        | What it does                                                                   |
| --------------------------- | ------------------------------------------------------------------------------ |
| `erdo_record_page_feedback` | Ingest one or more page-feedback items; mints a `defect` observation per item. |

### REST

Base URL `https://api.erdo.ai`. `Authorization: Bearer <token>` + `X-Organization-ID`.

| Method | Path                |
| ------ | ------------------- |
| `POST` | `/v1/page-feedback` |

`POST /v1/page-feedback` takes `{"items": [...]}`, each item `{experiment_slug, variant_key,
feedback, image_bucket_key?}`. The response carries one result per submitted item, in the same
order, naming the experiment, the variant, and the id of the observation it minted.

Attaching an image first: upload it with `erdo_upload_image` / `POST /v1/images/upload` (base64
bytes in, a `bucket_key` back), then pass that key as `image_bucket_key` on the page-feedback item.
