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

# Storefront extensions

> Put your app on the merchant's storefront with scripts, app embeds and app blocks

An app can reach a store's storefront in three ways:

| | What it is | Who turns it on | Needs a scope |
| - | - | - | - |
| **Script** | Raw HTML your app writes into the page head through the scripts API | Your app, through the API | `WRITE_SCRIPTS` |
| **App embed** | A script (and optional stylesheet) on every page, declared once for your app | The merchant, per store | No |
| **App block** | A widget with settings that a theme places on a page | Available on install; the merchant can switch it off | No |

All three belong to the install. When the merchant uninstalls your app, or the
app is suspended, none of them run on the storefront any more.

## Scripts

`POST /api/v1/scripts` with your app token:

```json theme={null}
{ "code": "<script src=\"https://cdn.example.com/pixel.js\" async></script>", "enabled": true }
```

* The script is tied to your install. You can only list, change and delete
  scripts your own install created; the merchant's pixels and other apps'
  scripts are invisible to you (`404`).
* `integration` is optional for apps.
* Uninstalling switches your running scripts off. If the merchant reinstalls
  your app and grants `WRITE_SCRIPTS` again, the scripts that were on come back
  on. So after an install, call `GET /api/v1/scripts` before creating scripts,
  or a reinstall gives you duplicates.
* The merchant sees your scripts under Integrations, "Added by apps", with your
  app's name, and can switch them off or remove them.

## Declaring embeds and blocks

In the developer console, open your app and fill **Storefront extensions**, or
send `extensions` with `PUT /api/v1/apps/developer/:id`:

```json theme={null}
{
  "embeds": [
    {
      "key": "chat-bubble",
      "name": "Chat bubble",
      "description": "Floating help button on every page",
      "scriptUrl": "https://cdn.example.com/bubble.js",
      "styleUrl": "https://cdn.example.com/bubble.css",
      "position": "body"
    }
  ],
  "blocks": [
    {
      "key": "review-stars",
      "name": "Review stars",
      "description": "Average rating for a product",
      "scriptUrl": "https://cdn.example.com/stars.js",
      "settings": [
        { "key": "size", "label": "Size", "type": "select", "options": ["small", "large"], "default": "small" },
        { "key": "color", "label": "Star colour", "type": "color", "default": "#f5a623" },
        { "key": "showCount", "label": "Show count", "type": "toggle", "default": true }
      ]
    }
  ]
}
```

Rules:

* `key`: lowercase letters, numbers and dashes, up to 40 characters, unique in its list.
* `scriptUrl` (required) and `styleUrl`: `https://` on a public host name.
* `position` (embeds): `head` or `body` (default).
* Block `settings[].type`: `text`, `textarea`, `number`, `toggle`, `color` or
  `select` (with `options`). A default that does not fit its type is replaced.
* Up to 10 embeds, 20 blocks, 20 settings per block.

Merchants see your declared extensions on your marketplace listing before they
install. A change to your declaration reaches stores within five minutes.

## App embeds

Each embed is off until the merchant switches it on (Apps, Installed, "On your
storefront"). Then every storefront page gets:

```html theme={null}
<link rel="stylesheet" href="https://cdn.example.com/bubble.css" data-salesive-app="your-app" data-salesive-embed="chat-bubble">
<script src="https://cdn.example.com/bubble.js" async data-salesive-app="your-app" data-salesive-embed="chat-bubble"></script>
```

Read `window.SALESIVE_CONFIG` for the store's name, type and currency.

## App blocks

### Writing a block

The block's script registers a mount function at its top level:

```js theme={null}
import { registerAppBlock } from "salesive-dev-tools/app-blocks";

registerAppBlock("review-stars", (el, { settings, context, shopId }) => {
  el.innerHTML = `<span style="color:${settings.color}">★★★★☆</span>`;
  return () => { el.innerHTML = ""; }; // optional cleanup
});
```

* `el` is the placeholder element; your block owns its contents.
* `settings` is the placement's settings over the defaults you declared.
* `context` is what the theme passed about the page, for example `{ productId }`.
  Document what your block reads.
* Without the SDK: `window.SalesiveAppBlocks.register("your-app/review-stars", mount)`,
  or push `["review-stars", mount, "your-app"]` onto `window.__salesiveAppBlockQueue`
  when the loader may not have run yet.

Your script loads once per page, the first time a placeholder for your block
appears. A block that throws is logged and skipped; it never breaks the page.

### Placing a block in a theme

```jsx theme={null}
import { SalesiveAppBlock, SalesiveAppBlocks } from "salesive-dev-tools/app-blocks";

<SalesiveAppBlock block="reviews/review-stars" settings={{ size: "large" }} context={{ productId }} />

// A slot the merchant arranges; the value is an array of { id, block, settings }
<SalesiveAppBlocks value={config.productBelowPrice} context={{ productId }} />
```

Or in plain HTML:

```html theme={null}
<div data-salesive-app-block="reviews/review-stars"
     data-salesive-block-settings='{"size":"large"}'
     data-salesive-block-context='{"productId":"665f..."}'></div>
```

A block the store does not have (app not installed, suspended, or the block
switched off) renders nothing. The storefront adds `window.SALESIVE_APPS` (the
store's available blocks) and the `/app-blocks.js` loader only when the store
has at least one block.

> [!NOTE]
>
> Merchant placement from the theme editor (a `salesive.form.json` field of type
> `appBlocks`) is designed but not live yet. Today a theme places blocks in code.

## Security

Embed and block code runs in the storefront page with the same reach as a
script. Registering a block is not a boundary between apps. Keep your script
URLs on a host you control, and serve them over https.


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