> For the complete documentation index, see [llms.txt](https://docs.sparkloop.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sparkloop.app/client-api/recommendations.md).

# Recommendations

Recommendation methods live under `SL.client.recommendations`. They all return promises and work with the [Recommendation object](/client-api/objects/recommendation.md).

The expected flow is a single, short-lived pass: `generate` (or `fetch`) → display → `subscribe`. Keep the time between generating and subscribing as short as possible.

{% hint style="warning" %}
Never cache or store recommendations. If a recommendation is no longer recommendable when your `subscribe` call arrives, it is discarded — see [Errors & Warnings](/client-api/errors-and-warnings.md).
{% endhint %}

### generate({ limit })

Generates fresh recommendations for the current reader.

* `limit` *(optional)* — number of recommendations to generate. Defaults to `5`, maximum `50`.

Returns an array of [Recommendation](/client-api/objects/recommendation.md) objects.

```js
const recommendations = await SL.client.recommendations.generate({ limit: 5 });
```

{% hint style="warning" %}
Only generate the number of recommendations you're actually going to display. Generating more than you show inflates your metrics and hurts your performance.
{% endhint %}

### fetch({ uuid })

Fetches a single recommendation by its uuid.

* `uuid` *(required)* — the recommendation's uuid.

Returns a single [Recommendation](/client-api/objects/recommendation.md) object, including the `recommendable` field.

Use `fetch` to spotlight a specific recommendation — for example, one that is contextual to the content surrounding it. It is not meant as an extra step between `generate` and `subscribe`: recommendations you just generated can be subscribed to directly.

Always check `recommendable` before displaying a fetched recommendation. When it's `false`, don't show it — subscriptions to it will be discarded.

```js
const recommendation = await SL.client.recommendations.fetch({ uuid: "partner_campaign_23ac0811bfff" });

if (recommendation.recommendable) {
  // render the recommendation in your UI
}
```

### subscribe({ email, uuids, shownUuids })

Subscribes the reader to the recommendations they picked.

* `email` *(required)* — the reader's email address.
* `uuids` *(required)* — array of uuids of the recommendations the reader picked.
* `shownUuids` *(optional)* — array of uuids of the recommendations the reader actually saw. We strongly recommend sending it: it tells SparkLoop which recommendations actually got in front of your readers, which improves what gets recommended next and maximizes your earnings.

Returns `{ response: "ok" }`.

```js
await SL.client.recommendations.subscribe({
  email: "reader@example.com",
  uuids: pickedUuids,
  shownUuids: displayedUuids,
});
```

{% hint style="danger" %}
Readers must explicitly choose the recommendations you subscribe them to. Misleading readers into subscribing without their consent results in a permanent block of your SparkLoop account.
{% endhint %}

### Tracking shown recommendations

`shownUuids` should contain the recommendations the reader actually saw — not everything you rendered. The simplest reliable way to measure that is an `IntersectionObserver`: count a recommendation as shown once at least half of its card has been visible in the viewport.

```js
const shownUuids = new Set();

const observer = new IntersectionObserver((entries) => {
  for (const entry of entries) {
    if (!entry.isIntersecting) continue;
    shownUuids.add(entry.target.dataset.recommendationUuid);
    observer.unobserve(entry.target);
  }
}, { threshold: 0.5 });

// After rendering, tag each card with its uuid and observe it
document.querySelectorAll("[data-recommendation-uuid]").forEach((el) => observer.observe(el));

// When the reader submits
await SL.client.recommendations.subscribe({
  email,
  uuids: pickedUuids,
  shownUuids: [...shownUuids],
});
```
