> For the complete documentation index, see [llms.txt](https://docs.overflowcms.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.overflowcms.com/webflow-integration/embed-script-basics.md).

# Embed Script Basics

## Embed Script Basics

One script, `embed.js` (≈10 KB, vanilla TypeScript, zero dependencies), powers every collection on every site — there's no per-collection build. It's served from the same host as the JSON API: `cdn.overflowcms.com`.

{% hint style="info" %}
If your site has a staging URL configured (see Publishing Workflow → Publishing to Production vs. Staging), this same script automatically shows only what's published to whichever environment the current page is loaded on — Production or Staging. No separate embed code, no extra attributes here; it's resolved server-side from the page's own URL on every request.
{% endhint %}

Every collection's **Integrate** tab generates the exact snippet below for you, with your site's real token and fields already filled in:

![The Integrate tab: embed script URL, JSON endpoint, and the 3-step Webflow setup](https://overflowcms.com/images/docs-screenshots/collection-integrate.png)

![The Integrate tab's field reference table](https://overflowcms.com/images/docs-screenshots/collection-integrate-2.png)

**Load it once**

```html
<script async src="https://cdn.overflowcms.com/embed.js" data-oc-token="pk_live_..."></script>
```

Put this in Webflow's **Site Settings → Custom Code → Head Code** (site-wide) or a single page's head. `data-oc-token` is your site's public token — see Core Concepts. The script self-initializes on `DOMContentLoaded` (or immediately if the DOM is already ready), scans for every `[data-oc-list]`, `[data-oc-search]`, and `[data-oc-related]` container on the page, and renders each independently.

**The list/item contract**

```html
<div data-oc-list="blog" data-oc-limit="12" data-oc-sort="-publishedDate">
  <div data-oc-item>
    <img data-oc-field="cover" alt="" />
    <h3 data-oc-field="title"></h3>
    <div data-oc-field="excerpt"></div>
    <a data-oc-link href="/blog/">Read more</a>
  </div>
  <div data-oc-empty>Nothing here yet.</div>
  <button data-oc-load-more>Load more</button>
</div>
```

* **`data-oc-list="<slug>"`** — the collection's slug (shown in the Integrate tab). One container per list; a page can have several.
* **`data-oc-limit`** / **`data-oc-sort`** — optional, forwarded straight to the JSON API's `limit`/`sort` query params (e.g. `-publishedDate` = descending). Only fields marked **indexed** on the collection can be sorted on.
* **`[data-oc-item]`** — the template. The script detaches this node on load, clones it once per returned item, and re-inserts the clones — the original is never itself shown. It doesn't have to be a direct child of the container — see “Giving the cards their own layout” below. Style it however you like in the Designer; the only thing that matters to the script is the attributes on the elements inside it.
* **`[data-oc-empty]`** — shown only when the first page returns zero items; hidden otherwise.
* **`[data-oc-load-more]`** — a button that fetches the next page and appends items, rather than replacing them. It's hidden automatically once you're on the last page.

{% hint style="info" %}
This is button-triggered pagination, not scroll-triggered infinite scroll — the button has to be clicked. Need filter dropdowns, checkboxes, or click-to-sort headers instead of (or alongside) this? See Filtering & Sorting for `data-oc-filter`, `data-oc-sort-toggle`, and `data-oc-sort-select` — declarative controls that live inside the same block. Semantic **search** is different again — it's a separate widget (`data-oc-search`, Pro plan+) that matches by meaning via Workers AI rather than filtering a list by an exact field value. See AI Search & Related Items.
{% endhint %}

**Giving the cards their own layout**

`[data-oc-item]` doesn't need to sit directly inside `[data-oc-list]`/`[data-oc-search]`/`[data-oc-related]` — nest it inside its own wrapper to scope a layout like `display: grid` to just the cards, keeping a loading indicator, empty state, or load-more button outside of it and unaffected:

```html
<div data-oc-list="blog" data-oc-limit="12">
  <div class="cards-grid"> <!-- put display: grid on this element, not on data-oc-list -->
    <div data-oc-item>
      <img data-oc-field="cover" alt="" />
      <h3 data-oc-field="title"></h3>
    </div>
  </div>
  <div data-oc-empty>Nothing here yet.</div>
  <button data-oc-load-more>Load more</button>
</div>
```

Clones always land in whichever element was the template's immediate parent — one level deep, several levels deep, doesn't matter. `[data-oc-empty]` and `[data-oc-load-more]` can live inside that wrapper too if you'd rather; both placements work.

**Binding fields**

Inside `[data-oc-item]`, anything with `data-oc-field="<key>"` gets that field's value bound in:

| Element / attribute                         | Behavior                                                                                                                                                                                                                       |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `<img data-oc-field="cover">`               | Sets `src`, `srcset` (if present), and `alt`. Adds `sizes="100vw"` automatically when a width-descriptor srcset is present and you haven't set your own `sizes`.                                                               |
| `data-oc-field="body" data-oc-html`         | Sets `innerHTML` — use for richText fields. (The script also treats any field whose *key* contains "rich", case-insensitively, as HTML even without the attribute — but the explicit attribute is the reliable way to opt in.) |
| `data-oc-field="date"` (ISO datetime value) | Sets `textContent` to a locale-formatted date (e.g. `Jul 11, 2026`) instead of the raw ISO string; binding to a `<time>` element also sets a spec-correct `datetime` attribute.                                                |
| `data-oc-field="title"` (default)           | Sets `textContent` — the safe default for everything else.                                                                                                                                                                     |

`data-oc-field` also accepts dotted paths (e.g. `author.name`) to reach into a resolved reference field.

**Attribute passthrough:** `data-oc-attr-href="slug"` on any element sets that element's `href` attribute to the item's `slug` field value (or any other field, by name). **Link helper:** `[data-oc-link]` appends the item's slug onto whatever `href` is already there — e.g. `href="/blog/"` becomes `href="/blog/my-post-slug"`.

Fields with no value are left untouched — the script never writes `null`/`undefined` over existing markup.

**Loading & error states**

No extra markup needed — every `[data-oc-list]`, `[data-oc-search]`, and `[data-oc-related]` container is a style hook on its own:

| Attribute         | When it's set                                                                                                                                                                                                                                                   | What to do with it                                                                                                                                                                                                                                                         |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-oc-loading` | Added to the container the moment a fetch starts (list load, load-more, a search keystroke, a related-items lookup); removed as soon as that fetch resolves (success or failure). Empty-string boolean attribute — its *presence* is the signal, not its value. | Style a skeleton or spinner state directly off it in Webflow's Designer (custom code, or a class toggle via a `[data-oc-loading]` CSS selector) — no JavaScript required. Example: `[data-oc-list][data-oc-loading] [data-oc-item] { opacity: .4; pointer-events: none; }` |
| `data-oc-error`   | Added to the container if a fetch throws or returns a non-2xx status (e.g. a plan-gated `403 plan_required` on search/related below Pro); cleared automatically on the next successful fetch.                                                                   | Show a fallback message with `[data-oc-error]::after { content: "Couldn't load this content." }`, or just leave the last-good content in place — the script never clears existing items on a failed fetch.                                                                 |

The underlying error is also logged to the browser console (`[OverflowCMS] list/search/related fetch failed …`) for your own debugging — it isn't surfaced in the DOM beyond the boolean `data-oc-error` attribute.

**Data attributes reference**

Every `data-oc-*` attribute the embed script reads or writes, in one place. Widget-scoping attributes go on the container; template-binding attributes go inside `[data-oc-item]`.

*On the `<script>` tag*

| Attribute       | Description                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
| `data-oc-token` | Required. The site's public token (`pk_live_…`) that scopes every API call to that site's published content.         |
| `data-oc-api`   | Optional. Overrides the API base URL (defaults to `https://cdn.overflowcms.com`) — mainly for local/staging testing. |

*Widget containers*

| Attribute                  | Widget                | Description                                                                                                                                             |
| -------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-oc-list="<slug>"`    | List                  | Marks the container as a paginated list for the given collection slug.                                                                                  |
| `data-oc-search="<slug>"`  | Search (Pro+)         | Marks the container as a search widget. Scope to one collection, or leave the value empty (`data-oc-search=""`) to search every collection on the site. |
| `data-oc-related="<slug>"` | Related (Pro+)        | Marks the container as a "related items" widget for the given collection.                                                                               |
| `data-oc-limit`            | List, Search, Related | Max items per page/request.                                                                                                                             |
| `data-oc-sort`             | List                  | Sort key, e.g. `-publishedDate` for descending. The field must be marked indexed.                                                                       |
| `data-oc-item-slug`        | Related               | Optional override for which item's related-set to fetch. Defaults to the last path segment of the current page URL.                                     |
| `data-oc-loading`          | List, Search, Related | Set by the script while a fetch is in flight; removed once it resolves. Style hook — see Loading & error states above.                                  |
| `data-oc-error`            | List, Search, Related | Set by the script if a fetch fails; cleared on the next successful fetch. Style hook — see Loading & error states above.                                |

*Inside the container, alongside the template*

| Attribute              | Description                                                                                                                                                                                                                                                                                                                                |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `data-oc-item`         | Marks the template element. Detached on load, cloned once per result. Doesn't have to be a direct child of the container — clones are inserted wherever the template's immediate parent was, so nesting it in its own wrapper (e.g. for a `display: grid` scoped to just the cards) works — see “Giving the cards their own layout” above. |
| `data-oc-empty`        | Shown when a fetch/search returns zero results; hidden otherwise.                                                                                                                                                                                                                                                                          |
| `data-oc-load-more`    | List only. A button that fetches and appends the next page; hidden automatically on the last page.                                                                                                                                                                                                                                         |
| `data-oc-search-input` | Search only. Put on the `<input>` a visitor types into; debounced \~250ms, fires once 2+ characters are entered.                                                                                                                                                                                                                           |

*Inside `[data-oc-item]` (the template)*

| Attribute               | Description                                                                                                                                                                                                                                                         |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-oc-field="<key>"` | Binds that field's value into the element. Accepts dotted paths (e.g. `author.name`) to reach into a resolved reference field. ISO datetime string values are auto-formatted for display (e.g. `Jul 11, 2026`); binding to a `<time>` element also sets `datetime`. |
| `data-oc-html`          | Combined with `data-oc-field`, renders the value as HTML (`innerHTML`) instead of text — use for richText fields.                                                                                                                                                   |
| `data-oc-attr-<name>`   | Attribute passthrough: sets the element's `<name>` attribute from the named item-data field (or the item's `slug`, e.g. `data-oc-attr-href="slug"`).                                                                                                                |
| `data-oc-link`          | Appends the item's slug onto the element's existing `href`.                                                                                                                                                                                                         |

{% hint style="info" %}
`data-oc-filter`, `data-oc-filter-op`, `data-oc-clear-filters`, `data-oc-sort-toggle`, and `data-oc-sort-select` are covered separately in Filtering & Sorting.
{% endhint %}

Next: Filtering & Sorting for live filter/sort controls, AI Search & Related Items for search boxes and related-item blocks, or Rendering Events & Animations to hook into GSAP/ScrollTrigger.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.overflowcms.com/webflow-integration/embed-script-basics.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
