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

# Automatisch een gratis cadeau toevoegen bij een drempel

> Een Cart SDK use case die een gratis cadeau toevoegt wanneer het winkelwagentotaal een drempel passeert, en het verwijdert als het totaal eronder zakt.

Houd het winkelwagentotaal in de gaten en houd een gratis cadeau ermee in sync: voeg het cadeau toe zodra de shopper een bestedingsdrempel passeert, verwijder het als hij er weer onder zakt.

<Note>
  Voor een door de merchant geconfigureerde versie met niveaus, regels per markt en een voortgangsbalk gebruik je het [Rewards](/nl/aftersell/cart/rewards-block)-block, zonder code. Dit is voor wanneer je regel iets is wat het block niet kan uitdrukken.
</Note>

<div id="the-snippet">
  ## Het snippet
</div>

Plak in **Cart settings → Custom script → Initialization**, en stel de twee constanten in:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const FREE_GIFT_VARIANT_ID = 1234567890; // the gift product's variant id
const THRESHOLD_CENTS = 5000;            // $50.00, since totals are in cents

function reconcileGift(state) {
  const gift = state.items.find((line) => line.variantId === FREE_GIFT_VARIANT_ID);
  const qualifies = state.totalPrice >= THRESHOLD_CENTS;

  if (qualifies && !gift) {
    window.aftersell.cart.actions.addItem(FREE_GIFT_VARIANT_ID, 1);
  } else if (!qualifies && gift) {
    window.aftersell.cart.actions.removeItem(gift.key);
  }
}

window.aftersell.cart.events.on('cart_loaded', reconcileGift);
window.aftersell.cart.events.on('cart_updated', reconcileGift);
```

<div id="how-it-works">
  ## Hoe het werkt
</div>

**`reconcileGift`** beschrijft de staat waarin de winkelwagen *zou moeten* zijn, en voert dan hoogstens één wijziging uit om daar te komen:

* Komt in aanmerking en het cadeau is er niet → [`addItem`](/nl/aftersell/cart/sdk-actions#additemvariantid-quantity) voegt het toe.
* Komt niet in aanmerking en het cadeau is er wel → [`removeItem`](/nl/aftersell/cart/sdk-actions#removeitemkey) verwijdert het, via de `key` van de regel.
* Anders → doe niets.

Het draait op zowel [`cart_loaded`](/nl/aftersell/cart/sdk-events#cart_loaded) (zodat een winkelwagen die bij het laden van de pagina al in aanmerking komt het cadeau krijgt) als [`cart_updated`](/nl/aftersell/cart/sdk-events#cart_updated) (zodat het daarna op elke wijziging reageert). Omdat `cart_loaded` opnieuw wordt afgespeeld voor late subscribers, werkt dit ongeacht wanneer je script draait.

<Warning>
  **De `!gift`- / `gift`-guards zijn wat dit tegen loopen beschermt.** Het cadeau toevoegen vuurt `cart_updated` af, wat `reconcileGift` opnieuw uitvoert, en de tweede doorloop vindt het cadeau al aanwezig, dus doet die niets. Haal de guards weg en je krijgt een oneindige loop. Zie [de twee regels](/nl/aftersell/cart/sdk-events#the-two-rules).
</Warning>

Merk op dat het toevoegen van het cadeau **het winkelwagentotaal verhoogt**, dus een drempel dicht bij de prijs van een product kan oscilleren: een cadeau van \$0 toevoegen is veilig, maar een cadeau met een prijs kan de winkelwagen op eigen kracht boven de drempel duwen. Houd het cadeau gratis, of vergelijk met een totaal dat het cadeau uitsluit.

<div id="adapting-it">
  ## Aanpassen
</div>

**Gate op aantal items in plaats van besteding:**

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const qualifies = state.itemCount >= 3;
```

**Gate op een specifiek product in de winkelwagen:**

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const qualifies = state.items.some((line) => line.productId === TRIGGER_PRODUCT_ID);
```

**Alleen in bepaalde landen.** Lees [`context`](/nl/aftersell/cart/sdk-overview#context), dat beschikbaar is voordat de winkelwagen laadt:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const ELIGIBLE = ['US', 'CA'];

// Only register the handlers for eligible countries.
if (ELIGIBLE.includes(window.aftersell.cart.context.customer_country)) {
  window.aftersell.cart.events.on('cart_loaded', reconcileGift);
  window.aftersell.cart.events.on('cart_updated', reconcileGift);
}
```

**Sluit het cadeau uit van de drempel** zodat het zichzelf niet in stand kan houden:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const subtotalWithoutGift = state.items.reduce(
  (sum, line) => (line.variantId === FREE_GIFT_VARIANT_ID ? sum : sum + line.finalLinePrice),
  0
);
const qualifies = subtotalWithoutGift >= THRESHOLD_CENTS;
```

**Markeer het cadeau zodat het als cadeau leest.** Een [line transform](/nl/aftersell/cart/sdk-hooks#registerlinetransform) kan de titel, varianttitel, verborgen staat en interne properties van een regel wijzigen — dus herlabel het:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.variantId === FREE_GIFT_VARIANT_ID) {
    line.setTitle('Free gift 🎁');
  }
});
```

<Note>
  Een line transform **kan de aantal-knoppen van een regel niet verbergen** — de enige setters zijn `setTitle`, `setVariantTitle`, `setHidden` en `setInternalProperties`. Als een shopper het aantal van het cadeau wijzigt, corrigeer dat dan vanuit een `cart_updated`-handler.
</Note>

<div id="where-to-go-next">
  ## Waar je verder kunt kijken
</div>

* **[Rewards block](/nl/aftersell/cart/rewards-block)**: de no-code-versie, met niveaus.
* **[Actions](/nl/aftersell/cart/sdk-actions)**: `addItem`, `removeItem` en de rest.
* **[Events](/nl/aftersell/cart/sdk-events)**: waarom de guards belangrijk zijn.
