> ## 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.

# Custom-Code-Blöcke

> Der Custom-Code-Block im Aftersell Cart: Füge eigenes HTML oder React an beliebiger Stelle im Drawer hinzu, auch innerhalb von Cart items.

> Der Block **Custom code** fügt dein eigenes HTML oder React zum Warenkorb hinzu. Platziere ihn in einem beliebigen Bereich des Drawers oder verschachtele ihn als Sub-Block innerhalb von [**Cart items**](/de/aftersell/cart/cart-items-block), sodass er für jede Position wiederholt wird. Anders als andere Blöcke hat er keine Content-Einstellungen und keinen Design-Bereich: Der Block *ist* der Code, du arbeitest also ausschließlich in seinem **Code**-Tab.

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-custom-code-block-add-and-enable.gif?s=6717cc64a8765b0c06b65990f99e12ff" alt="Animierte Vorschau, wie ein Custom-Code-Block im Aftersell Cart Editor hinzugefügt und aktiviert wird" title="Animierte Vorschau, wie ein Custom-Code-Block im Aftersell Cart Editor hinzugefügt und aktiviert wird" width="1200" height="558" data-path="images/aftersell/cart-custom-code-block-add-and-enable.gif" />
</Frame>

<div id="add-and-turn-on-a-custom-code-block">
  ## Einen Custom-Code-Block hinzufügen und aktivieren
</div>

1. Füge einen **Custom code**-Block zu einem beliebigen Bereich hinzu, oder als Sub-Block unter **Cart items**.
2. Wähle ihn aus und öffne den **Code**-Tab.
3. Wähle **HTML** oder **React component**. Neue Blöcke stehen standardmäßig auf HTML.
4. Schreibe deinen Code.
5. Wenn du React gewählt hast, klicke auf <span style={{display:'inline-flex',alignItems:'center',gap:'4px',background:'#1C1C1C',color:'#fff',border:'1px solid #0A0A0A',borderRadius:'4px',padding:'0 6px',fontSize:'0.85em',fontWeight:500,lineHeight:'1.4em',verticalAlign:'middle'}}><svg width="8" height="9" viewBox="0 0 10 12" fill="none" aria-hidden="true" style={{display:'block'}}><path d="M1.5 1.2v9.6L8.8 6 1.5 1.2Z" stroke="#fff" strokeWidth="1.5" strokeLinejoin="round" /></svg>Compile</span>.
6. Aktiviere **"Use custom template"**. Bei diesem Block bedeutet dieser Schalter „meinen Custom Code anzeigen“, und er ist standardmäßig aus — es wird also nichts gerendert, bis du ihn aktivierst.
7. Lass den Augen-Schalter in der Seitenleiste aktiviert, damit der Block für Käufer sichtbar bleibt.

Sowohl der Augen-Schalter als auch **"Use custom template"** müssen aktiviert sein, damit der Block erscheint.

<div id="behavior">
  ## Verhalten
</div>

* Der Block rendert nichts, bis der Warenkorb geladen ist.
* Er rendert außerdem nichts, wenn das Auge in der Seitenleiste ausgeschaltet ist, **"Use custom template"** deaktiviert ist, der Code leer ist oder React nicht kompiliert bzw. rendert. Da ein Fehler stillschweigend geschieht, prüfe deinen Block in der [Vorschau](/de/aftersell/cart/previewing-carts), bevor du veröffentlichst.

<div id="html-mode">
  ## HTML-Modus
</div>

Der HTML-Modus ersetzt eine kleine Menge an Tokens in deinem Markup. Er ist für statische oder token-basierte Inhalte gedacht, nicht für das Ausführen von Logik.

* **Inline-`<script>`-Tags werden nicht ausgeführt**, und der HTML-Modus hat **keinen Zugriff auf das SDK oder `window`.**
* Für Logik nutze den [**React-Modus**](#react-mode) oder [Custom Scripts](/de/aftersell/cart/custom-scripts) mit dem [Cart SDK](/de/aftersell/cart/sdk-overview).

<div id="tokens">
  ### Tokens
</div>

Token-Werte sind **formatierte Strings** (Geldformat des Shops, ein Prozentsatz mit `%` oder eine Menge), fertig zum Einsetzen ins Markup:

| Token                    | Was angezeigt wird                                                     |
| ------------------------ | ---------------------------------------------------------------------- |
| `{{pre_cart_total}}`     | Warenkorbsumme vor Rabatten.                                           |
| `{{post_cart_total}}`    | Warenkorbsumme nach Rabatten.                                          |
| `{{savings_amount}}`     | Gesparter Betrag (Summe vor Rabatt minus Summe nach Rabatt).           |
| `{{savings_percentage}}` | Ersparnis als Prozentsatz, inklusive `%`-Zeichen (zum Beispiel `15%`). |
| `{{cart_quantity}}`      | Anzahl der sichtbaren Artikel im Warenkorb.                            |

<div id="example">
  ### Beispiel
</div>

```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
<div class="cart-external-custom-code_html">
  You saved {{savings_amount}} ({{savings_percentage}})
</div>
```

<div id="react-mode">
  ## React-Modus
</div>

Der React-Modus kompiliert eine Komponente und übergibt ihr Warenkorbdaten sowie eine `add-to-cart`-Aktion.

* Der Editor fixiert den Wrapper auf `function CustomCode(props: CustomCodeProps) { … }`, und du bearbeitest nur den Rumpf zwischen diesen Zeilen.
* Du musst auf <span style={{display:'inline-flex',alignItems:'center',gap:'4px',background:'#1C1C1C',color:'#fff',border:'1px solid #0A0A0A',borderRadius:'4px',padding:'0 6px',fontSize:'0.85em',fontWeight:500,lineHeight:'1.4em',verticalAlign:'middle'}}><svg width="8" height="9" viewBox="0 0 10 12" fill="none" aria-hidden="true" style={{display:'block'}}><path d="M1.5 1.2v9.6L8.8 6 1.5 1.2Z" stroke="#fff" strokeWidth="1.5" strokeLinejoin="round" /></svg>Compile</span> klicken und dann **"Use custom template"** aktivieren, bevor der Block angezeigt wird.
* Deine Komponente kann `useState`, `useEffect`, `useMemo`, `useRef` und `useCallback` verwenden.
* Anders als im HTML-Modus läuft React im Seitenkontext und kann daher `window` und das [Cart SDK](/de/aftersell/cart/sdk-overview) aufrufen, sofern verfügbar.
* Wenn deine Komponente zur Laufzeit Fehler wirft, rendert der Block nichts, und der Rest des Warenkorbs funktioniert weiter.

<div id="props">
  ### Props
</div>

Summen und Ersparnisbeträge sind Ganzzahlen in der [kleinsten Einheit](/de/aftersell/cart/sdk-actions#formatmoneycents) der Währung (Cent bei USD), also ist `$12.50` gleich `1250`, nicht `12.50`. Es sind keine formatierten Geld-Strings wie bei den HTML-Tokens.

| Prop                                            | Typ                         | Beschreibung                                                                                                                                        |
| ----------------------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cart`                                          | `AftersellCart`             | Der aktuelle Warenkorb. Siehe die [Cart-Objekt-Referenz](/de/aftersell/cart/sdk-cart-object).                                                       |
| `line`                                          | `AftersellCartLine \| null` | Nur gesetzt, wenn der Block ein Cart-items-Sub-Block ist (ein Render pro Position); `null` in einem Bereich.                                        |
| `preCartTotal`                                  | `number`                    | Die Warenkorbsumme **vor Rabatten** (Shopifys `original_total_price`), in der kleinsten Einheit der Währung (z. B. Cent).                           |
| `postCartTotal`                                 | `number`                    | Die Warenkorbsumme **nach Rabatten**, in der kleinsten Einheit der Währung.                                                                         |
| `savings`                                       | `{ amount, percentage }`    | Ersparnisbetrag und Prozentsatz.                                                                                                                    |
| `addProduct(variantId, quantity?, properties?)` | `function`                  | Fügt dem Warenkorb ein Produkt hinzu, versehen mit der Attribution dieses Blocks, damit [Analytics](/de/aftersell/cart/analytics) es zuordnen kann. |

<div id="the-cart-and-line-shapes">
  ### Die Strukturen von cart und line
</div>

`cart` und `line` sind dieselben Objekte, die das SDK überall sonst bereitstellt, daher sind sie einmalig in der **[Cart-Objekt-Referenz](/de/aftersell/cart/sdk-cart-object)** dokumentiert: jedes Feld am Warenkorb, an einer Position und an einem Bundle.

Die Felder, die du am häufigsten brauchen wirst: `cart.items`, `cart.itemCount`, `cart.totalPrice`, `line.title`, `line.quantity`, `line.finalLinePrice`.

Drei Besonderheiten dieses Blocks:

* **`line` ist nur bei einem Cart-items-Sub-Block gesetzt**, wo deine Komponente einmal pro Position rendert. Als Bereich platziert ist `line` gleich `null`, und du liest stattdessen `cart.items`.
* **Bundle-Kinder sind nicht in `cart.items`.** Wenn Positionen [zu einem Bundle gruppiert](/de/aftersell/cart/sdk-use-case-bundles) sind, erscheint nur die Anker-Position; ihre Kinder liegen unter `line.bundle.children`.
* **Positionen, die durch eine [Line-Transform](/de/aftersell/cart/sdk-hooks#registerlinetransform) ausgeblendet wurden, fehlen ebenfalls**, obwohl sie weiterhin in `cart.totalPrice` einfließen.

<div id="examples">
  ### Beispiele
</div>

Die Artikelanzahl anzeigen:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  return (
    <div className="cart-external-custom-code_jsx">
      {props.cart.itemCount} items
    </div>
  );
}
```

Als Cart-items-Sub-Block nutzt du `props.line` für produktbezogene Inhalte. Der Block rendert einmal pro Position, versehen mit dem Produkt und der Variante dieser Position:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  if (!props.line) return null;
  return (
    <div className="cart-external-custom-code_jsx">
      {props.line.productTitle}
      {props.line.variantTitle ? ` · ${props.line.variantTitle}` : ''}
    </div>
  );
}
```

<div id="reading-enrichment-metadata">
  ### Enrichment-Metadaten auslesen
</div>

Jedes Element in `cart.items` trägt ein Feld `metadata`: ein leeres Objekt `{}`, bis ein [Cart Enricher](/de/aftersell/cart/sdk-hooks#registercartenricher) es befüllt. Danach ist es nach der `id` des Enrichers indiziert und enthält die Storefront-Daten für das Produkt oder die Variante dieser Position:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  return (
    <ul>
      {(props.cart.items ?? []).map((item) => {
        const note = item.metadata?.shipping?.shippingNote;
        return (
          <li key={item.key}>
            {item.title}
            {note ? ` · ${note.value}` : ''}
          </li>
        );
      })}
    </ul>
  );
}
```

`metadata` ist immer vorhanden und ist standardmäßig ein leeres Objekt `{}`, bis der asynchrone Fetch des Enrichers abgeschlossen ist (der Test auf „noch nicht angereichert“ ist `Object.keys(item.metadata).length === 0`). Verwende Optional Chaining (`item.metadata?.enricherId`), wenn du den Schlüssel eines bestimmten Enrichers liest, da dieser Schlüssel fehlt, bis die Anreicherung abgeschlossen ist.

<div id="reading-discount-codes-and-line-discounts">
  ### Rabattcodes und Positionsrabatte auslesen
</div>

`cart.discountCodes` listet die auf den Warenkorb angewendeten Rabattcodes auf, und `discountAllocations` jeder Position listet die Rabatte auf, die auf genau diese Position angewendet wurden:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const codes = props.cart.discountCodes;
  return (
    <div>
      {codes.length > 0 && (
        <p>Active discounts: {codes.join(', ')}</p>
      )}
      <ul>
        {(props.cart.items ?? []).map((item) => {
          return (
            <li key={item.key}>
              {item.title}
              {item.discountAllocations.map(
                (discount) => ` · ${discount.title} (-${(discount.amount / 100).toFixed(2)})`
              )}
            </li>
          );
        })}
      </ul>
    </div>
  );
}
```

<div id="placement-and-limits">
  ## Platzierung und Limits
</div>

* **Bereich:** beliebig (oben, Hauptbereich oder unten). Auch als Cart-items-Sub-Block verfügbar.
* **Maximum:** unbegrenzt.
* **Zustand:** gefüllter und leerer Warenkorb (als Bereichsblock). Als Cart-items-Sub-Block rendert er nur, wenn der Warenkorb Positionen enthält, eine Instanz pro Position.
* Nicht gesperrt, du kannst ihn also entfernen oder ausblenden.
* Es gibt keinen blockeigenen Design-Bereich. Style ihn über dein eigenes Markup, [**Custom CSS**](/de/aftersell/cart/custom-css) und deine globalen [**Design settings**](/de/aftersell/cart/design-settings).

<div id="when-to-use-custom-code-block-vs-custom-template-vs-custom-script">
  ## Wann Custom-Code-Block vs. Custom Template vs. Custom Script
</div>

|                                                            | Was es tut                                                                                               | Wann du es einsetzt                                                 | Beispiel                                                                                                                                                                                                                     |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Custom-Code-Block**                                      | Fügt einen *neuen* Block mit deinem eigenen HTML oder React hinzu.                                       | Etwas, das die integrierten Blöcke nicht abdecken.                  | Eine geschätzte Gesamtsumme, die deine Versandpauschale zur Warenkorbsumme addiert, oder ein Lieferschluss-Countdown über dem Checkout-Button.                                                                               |
| **[Custom Template](/de/aftersell/cart/custom-templates)** | Ersetzt das Rendering eines *bestehenden* Blocks durch dein JSX und nutzt dabei die Daten dieses Blocks. | Der integrierte Block passt fast, aber du brauchst anderes Markup.  | Baue die [Produktzeile](/de/aftersell/cart/cart-items-block#custom-template) so um, dass Variantenname, Ersparnis und Mengenauswahl in einer Zeile stehen.                                                                   |
| **[Custom Script](/de/aftersell/cart/custom-scripts)**     | Führt JavaScript gegen den Warenkorb über das [Cart SDK](/de/aftersell/cart/sdk-overview) aus.           | Warenkorbweite Logik, Events und Konfiguration statt Drawer-Markup. | 75 \$ ausgeben, Gratis-Tasche erhalten: [das Geschenk hinzufügen](/de/aftersell/cart/sdk-use-case-free-gift), sobald der Warenkorb den Schwellenwert überschreitet, und es wieder entfernen, wenn der Käufer darunter fällt. |
