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

# Collect responses

> Let viewers send answers, picks, and feedback from your page straight into Shareable — no form service, no setup.

A Shareable page can **send what viewers enter back to you**. Add a form (or one line of
JavaScript) to your page, publish it, and every answer lands on the page's **Responses**
view in your dashboard, where you can read each one, see a summary per question, and export a
CSV. Your agent can read them back too.

There's no schema to set up and no form builder. Whatever the page sends is stored as it was
sent, and Shareable works out how to show each field.

<Note>
  Responses are **form data sent to you**, the page's owner. They aren't a database your page
  can read from: a page can send a response, but it can't read back other viewers' answers.
</Note>

## You don't add it, your AI does

Ask the AI that builds your page:

> *"Make this a feedback form that sends the answers to Shareable."* ·
> *"Add a Submit button that sends my picks to Shareable instead of downloading a file."*

If your AI publishes with the [Shareable MCP server](/mcp-server), it already knows how. The
tool descriptions explain both ways below.

## Two ways to send a response

<Tabs>
  <Tab title="A plain form (no JavaScript)">
    Add `data-shareable` to an ordinary `<form>`. Shareable handles the submit, sends the
    fields, and replaces the form with a thank-you message.

    ```html theme={null}
    <form data-shareable data-shareable-success="Thanks! Got it.">
      <label>Your name <input name="name" required></label>

      <label>Attending?
        <select name="attending">
          <option>Yes</option><option>No</option><option>Maybe</option>
        </select>
      </label>

      <label>Guests <input name="guests" type="number" min="0" value="0"></label>

      <label><input name="vegetarian" type="checkbox"> Vegetarian meal</label>

      <textarea name="note" data-label="Anything else?"></textarea>

      <button>Send RSVP</button>
    </form>
    ```
  </Tab>

  <Tab title="Any JSON (custom UIs)">
    For a page with its own interface (toggles, rankings, a picker), build an object and call
    `Shareable.submit`. It accepts any JSON object, including nested objects and lists.

    ```html theme={null}
    <button id="send">Send my picks</button>
    <p id="status"></p>
    <script>
      document.getElementById('send').onclick = async () => {
        const data = { reviewer: 'Dana', favorite: 'B', scores: { clarity: 4, tone: 5 } }
        const status = document.getElementById('status')

        // Always guard: Shareable only works on the live link (not in a saved copy).
        const res = window.Shareable ? await Shareable.submit(data) : { ok: false }
        if (res.ok) {
          status.textContent = 'Sent ✓'
        } else {
          if (res.error) status.textContent = res.error
          downloadJson(data) // fallback: save the answers as a file instead
        }
      }

      function downloadJson(data) {
        const a = document.createElement('a')
        a.href = URL.createObjectURL(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }))
        a.download = 'my-response.json'
        a.click()
      }
    </script>
    ```

    `Shareable.submit(data)` returns a promise:

    * `{ ok: true, id, updated }` — saved. `updated` is `true` when it replaced this viewer's
      earlier response.
    * `{ ok: false, error, reason }` — not saved. `error` is a short message you can show the
      viewer (for example, collection is closed, or the page has reached its response limit).

    An optional second argument adds a display name and column labels:
    `Shareable.submit(data, { name: 'Ada', labels: { q3: 'How likely are you to recommend us?' } })`.
    In a form, a field called `name` is used as the display name automatically.
  </Tab>
</Tabs>

### Always guard with `window.Shareable`

Shareable adds `window.Shareable` to your **live link** whenever the page contains a
`data-shareable` form or a `Shareable.submit(` call. If you close collection, it's still there,
and `submit` returns `{ ok: false }` with a message. In your dashboard preview it's a stand-in
that answers "Responses are only collected on the live link." In a copy of the page someone
saved and opened from their computer it may be missing, or still there with every `submit`
failing (`{ ok: false }`), since only the live link can send. Write the page so it still works
either way:

```js theme={null}
if (window.Shareable) await Shareable.submit(data)
else downloadJson(data) // or copy to the clipboard, or show the answers to copy
```

A `<form data-shareable>` needs no guard. Shareable handles it.

## How collection turns on

You don't flip a switch. When you publish, Shareable looks at the page's HTML: if it contains
a `data-shareable` form or a `Shareable.submit(` call, the page starts **collecting
responses**. Publish a version without either one and collection turns off again. It's checked
on every publish.

For a [multi-page deck](/guides/multi-page-decks), any HTML file in the deck counts. Keep the
`Shareable.submit(` call in the HTML (an inline `<script>`). A call that lives only in a
separate `.js` file isn't detected.

<Note>
  **The dashboard preview doesn't collect.** In the preview, `Shareable.submit` resolves with
  `ok: false` and a `data-shareable` form shows *"Responses are only collected on the live
  link."* That's how you can tell the button is wired up. To test it for real, open the
  published link.
</Note>

## How form fields are sent

For a `<form data-shareable>`, each input's `name` becomes a field, and the input type decides
what's sent:

| Input | Sent as |
| - | - |
| A checkbox that's the only one with its `name` and has no `value` attribute | `true` / `false` |
| A lone checkbox **with** a `value` attribute | a list: `[value]` when checked, `[]` when not |
| Several checkboxes sharing a `name` | a list of the checked values |
| `type="number"`, `type="range"` | a number |
| Radio buttons | the checked radio's `value` (always set one: a radio without it sends `"on"`) |
| `<select>` | the chosen option's `value` (its text when it has no `value`) |
| `<select multiple>` | a list of the chosen options |
| `<textarea>` and everything else | text |

* **Column names:** a field is shown under its `name`. Add `data-label="…"` to an input to
  show a friendlier label instead (for example `name="q3" data-label="How likely are you to
  recommend us?"`).
* **Thank-you message:** set `data-shareable-success="…"` on the form. The default is
  *"Thanks — your response was sent."* If something goes wrong, the error is shown next to the
  form instead.
* **Your own submit handlers still run.** Shareable stops the browser's normal form submission
  and sends the response, but it doesn't block other listeners: an `onsubmit` handler or
  `addEventListener('submit', …)` on the form (for analytics or UI) still fires. It can't cancel
  Shareable's submission, though: calling `preventDefault()` there doesn't stop the response from
  being sent. The browser's built-in checks (`required`, `type="email"`, `min`/`max`) do run
  first, and an invalid form isn't sent.
* **Need your own validation or flow?** Leave `data-shareable` off the form, handle `submit`
  yourself, and call `Shareable.submit(data)` when you're ready to send (see the JSON tab above).

## Reading your responses

Open the page in your dashboard and click **Responses**. You get:

* **Summary:** one card per field, summarized by its type (below).
* **Table:** one row per response, with who sent it and when. If responses contain a **list of
  items** (like one entry per question or per option), you can split it into **one row per
  item**, with the response's other fields copied onto each row.
* **A single response:** click a row to see every field, labelled.
* **Export:** download everything as **CSV** or **JSON**.

You can delete a single response or clear them all.

### How values are shown

Shareable works out each field's type from the values people actually sent:

| Values | Shown as | Summarized as |
| - | - | - |
| All `true`/`false` | Yes / No | % yes |
| All numbers | the number | average, min, max |
| Short text with a few repeating values | a choice | count per value |
| Lists of text | chips | count per value |
| Anything else | text | the answers, listed |
| A list of objects | a nested table | can be split into one row per item |

If a field mixes types, it's shown as text, so one odd value never breaks the view.

### From your agent or code

Your agent can read responses with the MCP tool [`get_responses`](/mcp-server#tools), or
call the REST API: [`GET /api/v1/pages/{id}/responses`](/api-reference/responses).

## Who sent it

Each viewer has **one response per page**. If they submit again, their new response replaces
the old one.

* On **verified email** and **specific people** pages, a response is labelled with the viewer's
  **verified email**.
* On every other page (anyone with the link, password), responses are **anonymous**,
  one per device (browser), and shown as an alias like *Anonymous · 3f9a07c2*. The alias is
  different on each page, so you can't match one person across pages.

Need to know who answered? Share the page as [verified email or specific
people](/guides/sharing-and-access).

## Limits

| | Free | Pro / Team |
| - | - | - |
| Responses per page | 100 | 10,000 |
| Total response data per page | 5 MB | 50 MB |
| One submission | up to 64 KB | up to 64 KB |

A resubmission replaces the viewer's earlier response, so it doesn't count as a new one. Once
a page reaches its limit, new submissions are refused with a message the page can show.
Submissions are also rate limited to keep a page from being flooded.

## Closing collection

To stop taking responses, **close** collection from the page in your dashboard. Responses you
already have are kept, and you can reopen it any time. Collection also stops when the link
expires or is unpublished. Responses aren't limited by the page's view limit: once a link
reaches it, no new viewers can open the page, but submissions to it are still accepted (up to
the response limits above) until you close collection.

## Privacy

* Responses are visible only to **you** (the page owner), in your dashboard, exports, and the
  API. Other viewers never see them.
* If your page asks for personal details, tell viewers what you're collecting and why. Don't
  ask for passwords or card numbers.
* Deleting a response, or the page, deletes the stored data. See our
  [privacy policy](https://useshareable.com/privacy).

## Not yet

* **Email alerts** for new responses. For now, check the Responses view (or have your agent
  call `get_responses`).
* **File uploads** in a response.
* **Reading responses back** from the page, for example to show a viewer what they sent last
  time.


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