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

# Migration der strapi-Datenstruktur (Version 5)

> Anleitung zur Migration bestehender Shops auf die neue strapi Datenstruktur: neues JSON-Ausgabeformat, Unterschiede zur alten Struktur und Anpassung der Shop-Templates.

export const ComingSoon = () => <span style={{
  display: 'inline-block',
  padding: '1px 10px',
  borderRadius: '9999px',
  fontSize: '0.75rem',
  fontWeight: 600,
  letterSpacing: '0.02em',
  backgroundColor: 'rgba(245, 158, 11, 0.18)',
  color: '#D97706',
  border: '1px solid rgba(245, 158, 11, 0.5)',
  verticalAlign: 'middle',
  whiteSpace: 'nowrap'
}}>
    Coming Soon
  </span>;

Auf dieser Seite wird beschrieben, wie bestehende Shops auf die neue strapi-Datenstruktur migriert werden. Durch die Umstellung vom bisherigen Content-Sync auf die neue Sync-Middleware ändert sich das Format der JSON-Dateien, die strapi an den Shop übergibt. Shop-Templates, die auf der alten Datenstruktur basieren, müssen dafür angepasst werden.

<Note>
  <ComingSoon />

  Die neue Sync-Middleware befindet sich derzeit in der Entwicklung. Auf dieser Seite wird die bereits bestätigte Datenstruktur beschrieben.
</Note>

## Gilt die neue Datenstruktur schon für meinen Shop?

Die neue Sync-Middleware wird mit dem Update auf strapi Version 5 eingeführt und ist ab dann der Standard. Vorher gibt es sie nicht. Daraus ergeben sich drei Fälle:

| **Ihr Shop**                                         | **Handlungsbedarf**                                                  |
| ---------------------------------------------------- | -------------------------------------------------------------------- |
| Nutzt strapi noch nicht                              | Keiner.                                                              |
| Wird neu mit strapi Version 5 eingerichtet           | Keiner. Der Shop erhält die neue Datenstruktur von Anfang an.        |
| Nutzt strapi bereits mit dem bisherigen Content-Sync | Einmalige Migration der Templates, wie auf dieser Seite beschrieben. |

## Was diese Seite behandelt und was nicht

Diese Seite behandelt das neue Ausgabeformat der JSON-Dateien, die Unterschiede zur alten Struktur und die dafür nötigen Template-Anpassungen.

**Nicht behandelt wird:**

* **Das Anlegen oder Erweitern von Inhalten in strapi.** Das ist unabhängig von der Migration. Grundlagen dazu stehen unter [Grundlagen & Architektur von strapi](/strapi-cms/grundlagen-architektur-von-strapi).
* **Die Darstellung neuer Inhaltsbausteine.** Ein Template stellt immer nur die Eingabemasken, Felder und Komponenten dar, die darin umgesetzt sind. Legt ein Redakteur eine neue Eingabemaske oder eine neue Komponente an, muss das Template dafür erweitert werden. Sowohl vor wie auch nach der Migration. Das Vorgehen steht unter [Templates für strapi Inhalte anpassen](/strapi-cms/templates-fur-strapi-inhalte-anpassen).

## Struktur dieser Anleitung

Die Anleitung besteht aus zwei Teilen. Teil A erklärt die Grundlagen, Teil B ist die eigentliche Arbeitsanleitung.

**Teil A – Grundlagen (Nachschlageteil):**

* [Begriffe: strapi in fünf Sätzen](#begriffe-strapi-in-funf-satzen)
* [Warum sich das Datenformat ändert](#warum-sich-das-datenformat-andert)
* [Die zwei neuen Formate im Vergleich](#die-zwei-neuen-formate-im-vergleich)
* [Das mapping-Format im Detail](#das-mapping-format-im-detail) und [Das schema-Format im Detail](#das-schema-format-im-detail)
* [Änderungen gegenüber der alten Struktur](#anderungen-gegenuber-der-alten-struktur)

**Teil B – [Templates migrieren: die acht Schritte](#templates-migrieren-die-acht-schritte):**

| **Schritt** | **Was passiert**                        | **Wann nötig**                                        |
| ----------- | --------------------------------------- | ----------------------------------------------------- |
| 1           | Betroffene Stellen im Template finden   | Immer                                                 |
| 2           | Testmodus-Weiche einbauen (Absicherung) | Immer, **vor** der ersten Änderung                    |
| 3           | Dateinamen in den Ladeaufrufen anpassen | Immer                                                 |
| 4           | Feldzugriffe umstellen                  | Immer                                                 |
| 5           | Inhaltsblöcke (Dynamic Zone) anpassen   | Wenn das Template Inhaltsblöcke rendert               |
| 6           | Medienzugriffe anpassen                 | Wenn Bilder oder Dateien aus strapi ausgegeben werden |
| 7           | SEO-Felder aus `meta` lesen             | Wenn das Template SEO-Angaben aus strapi ausgibt      |
| 8           | Im Testmodus prüfen und live schalten   | Immer, als letzter Schritt                            |

## Begriffe: strapi in fünf Sätzen

Diese fünf Begriffe werden auf der gesamten Seite verwendet und sind für die Verständlichkeit der Anleitung wichtig.

| **Begriff**                                 | **Bedeutung**                                                                                                                                                                                                                      |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Eingabemaske** (in strapi: Content-Typ)   | Die Vorlage, die festlegt, welche Eingabefelder ein Inhalt hat. Beispiel: eine Inhaltsseite mit den Feldern „Titel" und „Inhalt".                                                                                                  |
| **Eingabefeld** (Feld)                      | Ein einzelnes Feld dieser Maske. Jedes Feld hat einen technischen Feldnamen (beispielsweise `title`) und einen Feldtyp (Text, Bild, Ja/Nein …).                                                                                    |
| **Dokument**                                | Ein konkret ausgefüllter Inhalt, beispielsweise die Seite „AGB". Pro Dokument und Sprache entsteht ein eigener Satz JSON-Dateien für den Shop (siehe [Die zwei neuen Formate im Vergleich](#die-zwei-neuen-formate-im-vergleich)). |
| **Komponente**                              | Ein wiederverwendbarer Baustein aus mehreren Feldern, beispielsweise ein Button aus „Label" und „Link".                                                                                                                            |
| **Inhaltsblöcke** (in strapi: Dynamic Zone) | Ein Feld, in das der Redakteur beliebig viele Komponenten in beliebiger Reihenfolge einsetzt. Der typische Seitenaufbau einer Inhaltsseite.                                                                                        |

Im Folgenden bedeutet Feldzugriff: die Stelle im Template, die den Wert eines Eingabefeldes aus der geladenen JSON-Datei ausliest, beispielsweise den Seitentitel.

Ausführlicher sind diese Begriffe unter [Grundlagen & Architektur von strapi](/strapi-cms/grundlagen-architektur-von-strapi) beschrieben.

## Warum sich das Datenformat ändert

Die Shop-Templates lesen Inhalte über die technischen Feldnamen aus den JSON-Dateien. Bisher war das Format dieser Dateien eng an die interne REST-Struktur von strapi gekoppelt. Bei jedem großen strapi-Versionssprung (zuletzt Version 4 auf 5) konnte sich diese Struktur ändern, was Anpassungen an Shop und Templates erforderlich machte.

Die neue Sync-Middleware entkoppelt das Ausgabeformat von der strapi-internen Struktur. WEBSALE gibt damit eine eigene, feste Datenstruktur vor, die auch nach künftigen strapi-Updates stabil bleibt. Bestehende Shops müssen einmalig auf diese neue Struktur migriert werden. Danach sind sie updatefähig, ohne dass die Templates bei jedem strapi-Update angepasst werden müssen.

Ein zweiter Grund liegt in strapi selbst: Über den [Content-Type Builder](/strapi-cms/grundlagen-architektur-von-strapi) können berechtigte Benutzer nicht nur Inhalte pflegen, sondern auch die Eingabemasken verändern. Felder können angelegt, umbenannt oder gelöscht werden.

## Die zwei neuen Formate im Vergleich

Die neue Sync-Middleware schreibt jedes Dokument in zwei Dateien, in zwei unterschiedlichen Formaten. Beide enthalten dieselben Inhalte, nur anders angeordnet. Standardmäßig werden beide parallel erzeugt, damit ein schrittweiser Umstieg möglich ist.

Dasselbe Dokument („AGB", Felder `title` und `content`) sieht in den beiden Formaten so aus:

**mapping-Format** – jedes Eingabefeld ist direkt ein JSON-Key:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "title": "AGB",
  "content": [ … ]
}
```

**schema-Format** – jedes Eingabefeld ist ein Eintrag in einer Liste, immer mit denselben drei Schlüsseln:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "contentType": "api::contentpage.contentpage",
  "meta": { … },
  "fields": [
    { "name": "title",   "type": "string",      "value": "AGB" },
    { "name": "content", "type": "dynamiczone", "value": [ … ] }
  ]
}
```

Übersicht der Unterscheidungen:

|                                        | **mapping-Format**                                                                                   | **schema-Format**                                                                                                          |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| Dateiname                              | `<documentId>.json`                                                                                  | `<documentId>.schema.json`                                                                                                 |
| Template-Zugriff                       | direkt über den Feldnamen (`$cCMSData.title`)                                                        | über die Liste `fields`, einmalig in ein Name/Wert-Objekt überführt                                                        |
| Aufwand der Migration                  | gering – im Wesentlichen entfällt der `attributes`-Wrapper                                           | höher – die Feldzugriffe werden umgebaut                                                                                   |
| Wenn ein Feld in strapi umbenannt wird | Der **Aufbau der Datei ändert sich**: der JSON-Key heißt anders. Das Template muss angepasst werden. | Der **Aufbau der Datei bleibt gleich**, nur der Wert von `name` ändert sich. Das Template muss ebenfalls angepasst werden. |
| Wenn ein Feld hinzukommt oder wegfällt | Ein Key kommt hinzu oder fehlt.                                                                      | Ein Listeneintrag kommt hinzu oder fehlt.                                                                                  |
| Vorteil                                | einfachster Umstieg, kürzeste Templates                                                              | stabiler Dateiaufbau, Fehler sind leichter zu finden, Feldtyp ist mitgeliefert                                             |

<Info>
  Wichtig: **In beiden Formaten muss die Template-Stelle angepasst werden, wenn ein Eingabefeld umbenannt wird.** Kein Format schützt davor. Der Unterschied liegt nur darin, ob sich dabei der Aufbau der Datei ändert (mapping) oder nur ein Wert darin (schema).
</Info>

## Das mapping-Format im Detail

### Aufbau

Eine Inhaltsseite mit den Eingabefeldern „title" und „content" sieht so aus:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "title": "AGB",
  "content": [
    {
      "component": "elemente.ws-markup",
      "Markup": "AGB Content",
      "FullWidth": false
    }
  ],
  "_sync": { "contentType": "api::contentpage.contentpage" }
}
```

* Jedes Eingabefeld ist ein JSON-Key auf oberster Ebene. Der Wert steht direkt darunter.
* Der Schlüssel `_sync` ist kein Inhaltsfeld, sondern eine technische Ergänzung der Sync-Middleware. `_sync.contentType` nennt die Eingabemaske, aus der das Dokument stammt.
* Inhaltsblöcke stehen als Array unter ihrem Feldnamen (hier `content`). Jeder Block trägt seinen Komponenten-Namen in `component` – **nicht** mehr in `__component` wie in der alten Struktur – und seine Felder direkt daneben.
* Medien liegen als flaches, normalisiertes Medien-Objekt vor, identisch zum schema-Format (siehe [Medien](#medien-im-schema-format)). Der `data`/`attributes`-Wrapper der alten Struktur entfällt.

Der Aufbau entspricht damit weitgehend der bisherigen Struktur, jedoch ohne den `attributes`-Wrapper und mit den weiteren Änderungen aus der [Gegenüberstellung unten](#anderungen-gegenuber-der-alten-struktur).

### Was Sie beim mapping-Format beachten müssen

* **Feldnamen kommen ungefiltert durch.** Wird ein Eingabefeld in strapi umbenannt, ändert sich der JSON-Key. Die betroffene Template-Stelle muss dann angepasst werden. Das entspricht dem Verhalten, das Sie von benutzerdefinierten Produktdatenfeldern im Shop kennen.
* **Kein Feldtyp in der Datei.** Anders als im schema-Format steht nicht dabei, ob ein Wert ein Text, eine Zahl oder ein Medien-Objekt ist. Das Template muss das wissen.
* **Reservierte Namen.** Ein Feld, das in strapi `_sync` heißt, würde mit dem technischen Schlüssel kollidieren. Vermeiden Sie führende Unterstriche in Feldnamen.

<Note>
  Wo die SEO-Angaben des Meta-Info-Plugins im mapping-Format stehen, ist noch nicht abschließend festgelegt. Klären Sie das für Ihren Shop mit Ihrem WEBSALE Ansprechpartner, bevor Sie [Schritt 7](#schritt-7-seo-felder-aus-meta-lesen) auf Basis des mapping-Formats umsetzen. Im schema-Format stehen sie in `meta`.
</Note>

## Das schema-Format im Detail

Jede Datei des schema-Formats beschreibt genau ein Dokument, beispielsweise die Seite „AGB". Jede Datei besteht aus drei Bestandteilen:

| **Bestandteil** | **Inhalt**                                                                | **Details**                                                                         |
| --------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `contentType`   | Die technische Kennung der Eingabemaske, aus der das Dokument stammt.     | [Die Hülle](#die-hulle)                                                             |
| `meta`          | Verwaltungsdaten wie IDs und Zeitstempel sowie die SEO-Angaben der Seite. | [Verwaltungsdaten und SEO-Felder in meta](#verwaltungsdaten-und-seo-felder-in-meta) |
| `fields`        | Die eigentlichen Inhalte, also die Werte aller Eingabefelder.             | [Die Inhaltsfelder in fields](#die-inhaltsfelder-in-fields)                         |

Diese drei Bestandteile zusammen werden "Hülle" genannt. Es handelt sich dabei um den äußeren Rahmen jeder Datei, der immer gleich aussieht. Auch dann, wenn Eingabemasken in Strapi verändert werden.

Für die reine Migration genügt es, diesen Grundaufbau zu kennen. Die folgenden Unterabschnitte sind der Nachschlageteil für die konkrete Template-Anpassung.

### Die Hülle

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "contentType": "api::contentpage.contentpage",
  "meta": { … },
  "fields": [
    { "name": "…", "type": "…", "value": "…" }
  ]
}
```

| **Schlüssel** | **Typ** | **Bedeutung**                                                                                                                                                            |
| ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `contentType` | string  | Quell-UID der Eingabemaske, beispielsweise `api::contentpage.contentpage`. Die UID hat die Form `api::<name>.<name>` und ist in strapi im Content-Type Builder sichtbar. |
| `meta`        | object  | Von strapi bzw. der Sync-Middleware verwaltete Felder (siehe unten).                                                                                                     |
| `fields`      | array   | Die eigentlichen Inhaltsfelder, je `{ name, type, value }`.                                                                                                              |

<Info>
  Diese Hülle ist für alle Eingabemasken und Dokumente identisch. Das gilt auch, wenn Felder umbenannt, hinzugefügt oder gelöscht werden. Nur die Einträge innerhalb von `fields` ändern sich dadurch.
</Info>

### Verwaltungsdaten und SEO-Felder in meta

`meta` enthält die verwaltungsseitigen Felder eines Dokuments. Sie sind bewusst von den Inhaltsfeldern in `fields` getrennt:

| **Feld**                  | **Typ**           | **Hinweis**                                                                                                                                                                                               |
| ------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                      | number            | Interne numerische ID (pro Sprachversion).                                                                                                                                                                |
| `documentId`              | string            | Stabile, sprachübergreifende Dokument-ID. Bestimmt standardmäßig den Dateinamen.                                                                                                                          |
| `locale`                  | string            | Sprache dieser Datei, beispielsweise `de`. Der Sprachcode entspricht nicht zwangsläufig dem Verzeichnisnamen im Shop (beispielsweise `Deutsch`); die Zuordnung ergibt sich aus der Subshop-Konfiguration. |
| `createdAt` / `updatedAt` | string (ISO-8601) | Zeitstempel aus strapi.                                                                                                                                                                                   |
| `publishedAt`             | string oder null  | `null` bei Entwürfen.                                                                                                                                                                                     |

Ist für ein Dokument das Meta-Info-Plugin aktiv (siehe [SEO-Meta-Daten für CMS-Seiten](/strapi-cms/grundlagen-architektur-von-strapi#seo-meta-daten-fur-cms-seiten-meta-info-plugin)), enthält `meta` zusätzlich die SEO-Felder der Seite:

| **Feld**          | **Typ**   | **Hinweis**                                                                                                                                                                                                                                                                     |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`             | string    | SEO-URL der Seite.                                                                                                                                                                                                                                                              |
| `metaTitle`       | string    | Meta-Title.                                                                                                                                                                                                                                                                     |
| `metaDescription` | string    | Meta-Description.                                                                                                                                                                                                                                                               |
| `robots`          | string\[] | Ein Array, kein kommaseparierter String. Beispielsweise `["noindex", "nofollow"]`.                                                                                                                                                                                              |
| `hreflang`        | array     | Verweise auf die sprachlichen Entsprechungen derselben Seite, für die hreflang-Angaben im HTML-Head. Wird automatisch berechnet, sobald das Meta-Info-Plugin aktiv ist. Enthält einen Eintrag pro Subshop, der diese Sprache bedient (`{ language, url, subshopId, default }`). |

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
"meta": {
  "id": 99,
  "documentId": "l9h00uvgblpjvlqqv1va9s44",
  "locale": "de",
  "createdAt": "…", "updatedAt": "…", "publishedAt": "…",
  "url": "agb",
  "metaTitle": "AGB",
  "metaDescription": "Allgemeine Geschäftsbedingungen",
  "robots": ["noindex", "nofollow"],
  "hreflang": [
    { "language": "de", "url": "agb", "subshopId": "deutsch", "default": true }
  ]
}
```

<Warning>
  Eine Eingabemaske kann selbst Inhaltsfelder mit Namen wie `url` oder `robots` besitzen. Diese erscheinen dann als ganz normale Einträge in `fields` und sind etwas **anderes** als `meta.url` bzw. `meta.robots` (namensgleich, aber andere Bedeutung und teils andere Form). SEO-Werte aus dem Meta-Info-Plugin stehen immer in `meta` und niemals in `fields`. Verwechseln Sie beide beim Verarbeiten nicht.
</Warning>

### Die Inhaltsfelder in fields

`fields` ist eine Liste aller Eingabefelder des Dokuments. Jeder Eintrag hat exakt drei Schlüssel:

| **Schlüssel** | **Typ**        | **Bedeutung**                                                                                          |
| ------------- | -------------- | ------------------------------------------------------------------------------------------------------ |
| `name`        | string         | Der technische Feldname, wie er aktuell in der Eingabemaske heißt (kann sich durch Umbenennen ändern). |
| `type`        | string         | Der strapi Feldtyp (siehe [Feldtypen](#die-feldtypen)).                                                |
| `value`       | je nach `type` | Der Wert. Die Form hängt vom Typ ab.                                                                   |

Zwei Reihenfolgen sind dabei zu unterscheiden:

* **Reihenfolge der `fields`-Liste**: Sie folgt der Schema-Definition und ist fürs Rendern bedeutungslos. Greifen Sie deshalb immer über `name` und nie über die Position auf Felder zu.
* Die **Reihenfolge innerhalb eines Array-Werts** (Inhaltsblöcke, wiederholbare Komponenten, Relationslisten) ist layoutkritisch. Sie entspricht exakt der Anordnung des Redakteurs und muss beim Rendern übernommen werden.

### Die Feldtypen

**Skalare Typen**: `value` ist der Wert direkt.

| **type**                                       | **value**                                                                                            |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `string` / `text`                              | string oder null                                                                                     |
| `richtext`                                     | string oder null (Markdown oder bereits konvertiertes HTML, je nach Einstellung der Sync-Middleware) |
| `enumeration`                                  | string oder null                                                                                     |
| `boolean`                                      | boolean oder null                                                                                    |
| `integer` / `biginteger` / `decimal` / `float` | number oder null                                                                                     |
| `date` / `datetime` / `time` / `timestamp`     | string oder null                                                                                     |
| `uid`                                          | string oder null                                                                                     |
| `json`                                         | beliebiges JSON                                                                                      |
| `blocks`                                       | Array der strapi Blocks-Knoten oder HTML-String, je nach Einstellung der Sync-Middleware             |

<Info>
  Ob `richtext`- und `blocks`-Werte als Rohdaten (Markdown bzw. Blocks-JSON) oder als fertiges HTML ankommen, ist eine Deployment-Einstellung der Sync-Middleware. Klären Sie vor der Template-Anpassung mit WEBSALE, welche Variante für Ihren Shop aktiv ist.
</Info>

#### Medien im schema-Format

**`media`**: `value` ist ein normalisiertes Medien-Objekt mit festen Schlüsseln (`url`, `alt`, `caption`, `name`, `mime`, `ext`, `width`, `height`, `size`, `formats`). Strapi-Interna wie IDs, Hashes, Provider-Daten und Zeitstempel sind bewusst entfernt, damit strapi-interne Änderungen daran nicht im Shop ankommen. Fehlt ein Wert, ist er `null`. Bei Mehrfach-Medien ist `value` ein Array solcher Objekte.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "name": "logo",
  "type": "media",
  "value": {
    "url": "/uploads/websale_logo_576a45762c.webp",
    "alt": "Websale Firmenlogo",
    "caption": null,
    "name": "websale_logo.webp",
    "mime": "image/webp",
    "ext": ".webp",
    "width": 500,
    "height": 75,
    "size": 4.26,
    "formats": {
      "thumbnail": { "url": "/uploads/thumbnail_…", "width": 245, "height": 37, "mime": "image/webp", "size": 3.07 }
    }
  }
}
```

#### Komponenten und Relationen

**`component`**: `value` enthält eine eigene `fields`-Liste. Bei wiederholbaren Komponenten ist `value` ein Array solcher Objekte.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "name": "button",
  "type": "component",
  "value": {
    "fields": [
      { "name": "label", "type": "string", "value": "Mehr" },
      { "name": "link",  "type": "string", "value": "/info" }
    ]
  }
}
```

**`dynamiczone`** (Inhaltsblöcke): `value` ist ein Array von Blöcken. Jeder Block trägt seinen Komponenten-Namen in `component`, seine `id` und eine eigene `fields`-Liste.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "name": "content",
  "type": "dynamiczone",
  "value": [
    {
      "component": "elemente.ws-markup",
      "id": 96,
      "fields": [
        { "name": "Markup",    "type": "richtext", "value": "AGB Content" },
        { "name": "FullWidth", "type": "boolean",  "value": false }
      ]
    }
  ]
}
```

**`relation`**: `value` enthält die verknüpften Dokumente, rekursiv mit deren eigener `fields`-Liste. Eine Einzelrelation liefert ein Objekt, eine Mehrfachrelation ein Array. Die Auflösungstiefe ist begrenzt. Nicht mehr geladene tiefere Relationen erscheinen als `value: null`. Selbst-referenzierende Relationen (beispielsweise verschachtelte Navigationen) werden zusätzlich durch einen Zyklus-Schutz gekappt. Derselbe Typ wird pro Pfad nur einmal aufgelöst.

<Note>
  Beachten Sie die Ladetiefe auch im Template: `$wsExternalData.load` schneidet über die Option `maxDepth` tief verschachtelte Strukturen ab. In den Beispielen dieser Seite steht `maxDepth: 20`. Siehe [\$wsExternalData](/frontend/referenz/module/wsexternaldata).
</Note>

### Stabilitätsgarantie und ihre Grenze

**Stabil ist die Struktur:** Egal was an den Eingabemasken passiert, jede Datei ist `{ contentType, meta, fields[] }` und jedes Feld `{ name, type, value }`. Darauf können sich Templates zu 100 % verlassen.

**Nicht stabil ist die Bedeutung:** Benennt ein Redakteur ein Feld `title` in `titel` um, kommt das sauber durch. Im `name` steht dann aber `titel`. Ein Template, das gezielt nach `title` sucht, findet nichts mehr und gibt an dieser Stelle nichts aus. Die Zuordnung von Feldnamen zu ihrer Bedeutung ist eine Absprache zwischen Redaktion und Template-Verantwortlichen. Das Format kann dies nicht erzwingen. Einzige Ausnahme sind die SEO-Felder: Sie liegen über das Meta-Info-Plugin im schema-Format immer an derselben Stelle in `meta`, unabhängig davon, wie die Eingabemasken aufgebaut sind.

## Änderungen gegenüber der alten Struktur

Die folgende Übersicht stellt die neue Struktur der alten Datenstruktur des bisherigen Content-Syncs gegenüber. Sie ist die Grundlage für die Template-Anpassung im nächsten Abschnitt. Die Spalte „Neue Struktur" zeigt das schema-Format. Die Änderungen bei der Kennung der Eingabemaske, der Komponenten-Kennung, den Medien, `localizations` und den Dateinamen gelten für **beide** Formate. Bei den SEO-Feldern ist nur die Ablage im schema-Format (`meta`) bestätigt; für das mapping-Format ist sie noch offen.

| **Aspekt**               | **Alte Struktur**                                                                                                                                                   | **Neue Struktur (schema)**                                                                                                                                                                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Hülle                    | `{ "id", "attributes": { …alle Felder… }, "content_type" }` <br />Die Felder liegen in einem `attributes`-Wrapper.                                                  | `{ contentType, meta, fields[] }` <br />Es gibt keinen `attributes`-Wrapper mehr.                                                                                                                                                                                    |
| Kennung der Eingabemaske | kurzer Slug, beispielsweise `"contentpage"`                                                                                                                         | volle strapi-UID, beispielsweise `"api::contentpage.contentpage"`                                                                                                                                                                                                    |
| Komponenten-Kennung      | `"__component"`                                                                                                                                                     | `"component"` (auf den einzelnen Inhaltsblöcken)                                                                                                                                                                                                                     |
| Medien                   | REST-Wrapper `{ "data": { "id", "attributes": { … } } }` inklusive strapi-Interna                                                                                   | flaches, normalisiertes Medien-Objekt mit fester Schlüsselmenge (siehe oben)                                                                                                                                                                                         |
| SEO-Felder               | eigene Inhalts-Komponente (beispielsweise „Meta Information" mit `MetaTitle`, `MetaDescription`, `SeoURL`, `MetaRobots`), redaktionell in der Eingabemaske gepflegt | kein Inhaltsfeld mehr. Die Werte stehen über das Meta-Info-Plugin in `meta` mit neuen Namen: `SeoURL` → `url`, `MetaTitle` → `metaTitle`, `MetaDescription` → `metaDescription`, `MetaRobots` → `robots` (jetzt **Array** statt String). Neu hinzu kommt `hreflang`. |
| `localizations`          | immer vorhanden, auch leer                                                                                                                                          | komplett entfernt                                                                                                                                                                                                                                                    |
| Dateiname                | inhaltlich abgeleitet und sprechend, beispielsweise `tpl_about.json`                                                                                                | standardmäßig `documentId`-basiert, beispielsweise `l9h00uvgblpjvlqqv1va9s44.json`                                                                                                                                                                                   |

<Warning>
  Die Umstellung der Dateinamen auf die `documentId` betrifft jede Stelle im Template, die eine JSON-Datei über einen sprechenden Namen lädt. Die `documentId` ist die zentrale, stabile Identität eines Dokuments. Die numerische `id` eignet sich dafür nicht, da sie pro Sprachversion wechselt.
</Warning>

## Templates migrieren: die acht Schritte

Drei Hinweise vorab:

1. **Die Codebeispiele sind Muster zum Übertragen, kein Code zum unveränderten Kopieren.** Der Nachher-Code **ersetzt** die entsprechende bestehende Stelle in Ihrem Template – allerdings innerhalb der Testmodus-Weiche aus Schritt 2, sodass der bisherige Code für die Live-Ausgabe zunächst erhalten bleibt.
2. **Die Vorher-Beispiele zeigen ein typisches Muster der alten Struktur.** Da die alte Struktur je Shop unterschiedlich aufgebaut wurde, können die Stellen in Ihrem Shop abweichen.
3. **Arbeiten Sie von Anfang an hinter der Testmodus-Weiche** (Schritt 2). Sonst ändern Sie die Live-Ausgabe, bevor Sie sie geprüft haben.

Die Beispiele verwenden durchgehend das schema-Format, weil dort der größere Umbau anfällt. Wo sich das mapping-Format unterscheidet, ist es im jeweiligen Schritt genannt.

<Note>
  **Voraussetzung:** Die neuen Dateien müssen für Ihren Shop bereits erzeugt sein, sonst läuft der Testmodus ins Leere. Prüfen Sie im JSON-Verzeichnis, ob dort Dateien mit `documentId`-Namen liegen (`<documentId>.json` und `<documentId>.schema.json`). Die alten, sprechend benannten Dateien bleiben während der Umstellungsphase daneben erhalten. Aktivierung und Neuerzeugung veranlasst WEBSALE.
</Note>

### Schritt 1: Betroffene Stellen finden

**Wann nötig:** Immer.

Suchen Sie im Template-Repository (GitLab) nach allen Stellen, an denen strapi-JSON geladen oder gelesen wird:

* `$wsExternalData.load(` – lädt eine einzelne Datei. Relevant sind die Aufrufe mit der Option `source: "system"` und einem Pfad, der auf das JSON-Verzeichnis zeigt.
* `$wsExternalData.read(` – liest ein Verzeichnis und liefert eine Liste von Dateinamen zurück.
* die anschließenden Feldzugriffe auf die geladenen Daten, typischerweise erkennbar an `attributes` und `__component`.

Ergebnis ist eine Liste der Templates, die in den folgenden Schritten angepasst werden. Notieren Sie zu jedem Treffer, welches strapi-Dokument dort geladen wird – die Zuordnung „Datei ↔ Dokument" brauchen Sie in Schritt 3.

### Schritt 2: Testmodus-Weiche einbauen

**Wann nötig:** Immer, und zwar **vor** der ersten inhaltlichen Änderung.

Für die Prüfung ist keine zweite strapi-Instanz nötig. Da die alten Dateien während der Umstellungsphase erhalten bleiben, liegen alte und neue Dateien nebeneinander im JSON-Verzeichnis. Sie können deshalb im selben Template zwischen alt und neu umschalten: Im [Testmodus](/frontend/referenz/module/wstestmode) lädt und rendert das Template die neuen Dateien, die Live-Ausgabe arbeitet unverändert weiter mit den alten. So ist die Migration jederzeit abgesichert. Die Live-Seite bleibt bis Schritt 8 unangetastet.<br /><br />Die Weiche umfasst nicht nur den Ladeaufruf, sondern den gesamten Ausgabeblock\*\*.\*\* Die Feldzugriffe der neuen Struktur (Schritte 4 bis 7) passen nicht auf die alten Dateien. Würden Sie nur den Dateinamen umschalten, wäre die Live-Ausgabe sofort leer.

**Vorher (alte Struktur, ohne Weiche):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cCMSLoadOptions = {"source": "system", "type": "json", "maxDepth": 20} }}
{{ var $cCMSFile = ["json/Deutsch/tpl_about.json"] | join }}
{{ var $cCMSData = $wsExternalData.load($cCMSFile, $cCMSLoadOptions) }}
{{# … bisheriger Ausgabecode … #}}
```

**Nachher (mit Weiche – Gerüst, das Sie in den Schritten 3 bis 7 füllen):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cCMSLoadOptions = {"source": "system", "type": "json", "maxDepth": 20} }}
{{ if $wsTestMode.active }}
    {{# Testmodus: neue Struktur #}}
    {{ var $cCMSFile = ["json/Deutsch/l9h00uvgblpjvlqqv1va9s44.schema.json"] | join }}
    {{ var $cCMSData = $wsExternalData.load($cCMSFile, $cCMSLoadOptions) }}
    {{# … neuer Ausgabecode aus den Schritten 4 bis 7 … #}}
{{ else }}
    {{# Live: bisherige Struktur, unverändert #}}
    {{ var $cCMSFile = ["json/Deutsch/tpl_about.json"] | join }}
    {{ var $cCMSData = $wsExternalData.load($cCMSFile, $cCMSLoadOptions) }}
    {{# … bisheriger Ausgabecode … #}}
{{ /if }}
```

Alle folgenden Schritte arbeiten ausschließlich im oberen Zweig. Wie Sie den Testmodus im Shop aufrufen, steht unter [Testmodi des Shops ein-/ausschalten](/testmodi-des-shops-ein-ausschalten).

<Note>
  Umfangreichere Templates werden mit einer Weiche pro Ausgabestelle unübersichtlich. In diesem Fall ist es praktikabler, das alte Ausgabe-Template unverändert zu lassen und die neue Fassung als eigene Datei zu pflegen, die nur im Testmodus eingebunden wird. Das Vorgehen dazu ist unter [Templates für strapi Inhalte anpassen](/strapi-cms/templates-fur-strapi-inhalte-anpassen) beschrieben.
</Note>

### Schritt 3: Dateinamen in den Ladeaufrufen anpassen

**Wann nötig:** Immer.

**Der Pfad bleibt, nur der Dateiname ändert sich.** Die JSON-Dateien liegen weiterhin im selben Verzeichnis wie bisher: im JSON-Verzeichnis Ihres Shops, das die Templates über die Option `source: "system"` erreichen – beispielsweise `json/Deutsch/` für die deutschsprachigen Inhalte. Beide neuen Formate liegen dort **nebeneinander**, im selben Verzeichnis wie zuvor die alte Datei.

Statt eines sprechenden Namens trägt jede Datei standardmäßig die `documentId` des Dokuments:

|                | **Vorher**                    | **Nachher**                                         |
| -------------- | ----------------------------- | --------------------------------------------------- |
| mapping-Format | `json/Deutsch/tpl_about.json` | `json/Deutsch/l9h00uvgblpjvlqqv1va9s44.json`        |
| schema-Format  | (gab es nicht)                | `json/Deutsch/l9h00uvgblpjvlqqv1va9s44.schema.json` |

**So finden Sie die `documentId`:** Öffnen Sie das Dokument in strapi im Content-Manager. Die `documentId` steht dann in der Adresszeile des Browsers. Zusätzlich steht sie in jeder erzeugten Datei des schema-Formats unter `meta.documentId`.

*Screenshot: Content-Manager mit geöffnetem Dokument, `documentId` in der Adresszeile hervorgehoben.*

**Wo Sie anpassen:**

* In jedem `$wsExternalData.load(...)`-Aufruf, der eine strapi-Datei über ihren Namen lädt – im Gerüst aus Schritt 2 also der Wert von `$cCMSFile` im Testmodus-Zweig.
* **Nicht** in `$wsExternalData.read(...)`-Aufrufen. Diese lesen ein Verzeichnis ein und bleiben unverändert. Wertet Ihr Template die eingelesenen Dateinamen danach aber inhaltlich aus – beispielsweise, um aus dem Namen die passende Seite abzuleiten –, muss diese Logik ebenfalls angepasst werden, denn die Namen sind nicht mehr sprechend.

<Warning>
  Am häufigsten übersehen: Mapping-Dateien und selbstgebaute Namenskonventionen. Wenn Ihr Template den Dateinamen erst zur Laufzeit zusammensetzt (beispielsweise aus der aufgerufenen URL über eine eigene Mapping-Datei), muss diese Zuordnung auf `documentId`-Dateinamen umgestellt werden.
</Warning>

### Schritt 4: Feldzugriffe umstellen

**Wann nötig:** Immer. Der Umfang unterscheidet sich je nach Format.

Gemeint ist die Stelle, die den Wert eines Eingabefelds aus den geladenen Daten liest – beispielsweise den Titel der Seite.

**Beim mapping-Format** entfällt nur der `attributes`-Wrapper. Aus `$cCMSData.attributes.title` wird `$cCMSData.title`. Mehr ist an den Feldzugriffen nicht zu tun.

**Beim schema-Format** liegen die Werte nicht mehr direkt unter ihrem Feldnamen, sondern als Einträge in der Liste `fields`. Überführen Sie diese Liste einmal in ein Name/Wert-Objekt. Danach greifen Sie wie gewohnt über den Feldnamen zu:

Der Ladeaufruf aus Schritt 2 bleibt dabei unverändert. Ersetzt wird nur der Ausgabeteil darunter:

**Vorher (alte Struktur):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<h1>{{= $cCMSData.attributes.title }}</h1>
```

**Nachher (schema-Format):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $cCMSData }}
    {{# fields-Liste einmal in ein Name/Wert-Objekt überführen #}}
    {{ var $cFields = {} }}
    {{ foreach $cField in $cCMSData.fields }}
        {{ $cFields[$cField.name] = $cField.value }}
    {{ /foreach }}

    <h1>{{= $cFields.title }}</h1>
{{ /if }}
```

Die Prüfung `{{ if $cCMSData }}` ist kein Beiwerk: `$wsExternalData.load` gibt `null` zurück, wenn die Datei fehlt oder ungültig ist. Ohne diese Prüfung bleibt die Seite ohne jeden Hinweis leer.

Dieses Muster funktioniert auf jeder Ebene gleich: für die Felder des Dokuments, innerhalb von Komponenten (`value.fields`) und für die Blöcke der Inhaltsblöcke (siehe nächster Schritt).

### Schritt 5: Inhaltsblöcke (Dynamic Zone) anpassen

**Wann nötig:** Wenn Ihr Template die Inhaltsblöcke einer Seite rendert. Das betrifft praktisch jede Inhaltsseite mit frei kombinierbaren Komponenten.

Zwei Dinge ändern sich:

* Die Komponenten-Kennung heißt jetzt `component` statt `__component` – das gilt für **beide** Formate.
* Beim schema-Format liegen die Feldwerte eines Blocks in dessen eigener `fields`-Liste.

Ersetzen Sie den bestehenden Render-Code nach diesem Muster:

**Vorher (alte Struktur):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cItem in $cCMSData.attributes.content }}
    {{ if $cItem.__component == "elemente.ws-markup" }}
        <div>{{! $cItem.Markup }}</div>
    {{ /if }}
{{ /foreach }}
```

**Nachher (mapping-Format):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cItem in $cCMSData.content }}
    {{ if $cItem.component == "elemente.ws-markup" }}
        <div>{{! $cItem.Markup }}</div>
    {{ /if }}
{{ /foreach }}
```

**Nachher (schema-Format, `$cFields` aus Schritt 4):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cItem in $cFields.content }}
    {{ var $cItemFields = {} }}
    {{ foreach $cField in $cItem.fields }}
        {{ $cItemFields[$cField.name] = $cField.value }}
    {{ /foreach }}

    {{ if $cItem.component == "elemente.ws-markup" }}
        <div>{{! $cItemFields.Markup }}</div>
    {{ else }}
        {{# nicht umgesetzte Komponente: im Testmodus sichtbar machen #}}
        {{ if $wsTestMode.active }}
            <!-- Komponente "{{= $cItem.component }}" ist im Template nicht umgesetzt -->
        {{ /if }}
    {{ /if }}
{{ /foreach }}
```

Die Komponenten-Namen und Felder im Beispiel ersetzen Sie durch die Ihres Shops. Die Reihenfolge der Blöcke entspricht der Anordnung des Redakteurs und wird unverändert ausgegeben.

<Note>
  Behalten Sie einen `{{ else }}`-Zweig für unbekannte Komponenten bei bzw. ergänzen Sie einen. Sonst verschwindet ein neu angelegter Block still aus der Seite, statt aufzufallen.
</Note>

### Schritt 6: Medienzugriffe anpassen

**Wann nötig:** Überall dort, wo Bilder oder Dateien aus strapi ausgegeben werden. Gilt für beide Formate.

Der `data`/`attributes`-Wrapper um Medien entfällt. Bild-URL, Alternativtext und responsive Formate liegen direkt im normalisierten Medien-Objekt. Zusätzlich heißt der Alternativtext jetzt `alt` statt `alternativeText`. Ersetzen Sie die bestehenden Bild-Ausgaben nach diesem Muster:

**Vorher (alte Struktur):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<img src="{{= $cCMSData.attributes.logo.data.attributes.url }}"
     alt="{{= $cCMSData.attributes.logo.data.attributes.alternativeText }}">
```

**Nachher (schema-Format, `$cFields` aus Schritt 4):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<img src="{{= $cFields.logo.url }}" alt="{{= $cFields.logo.alt }}">
```

**Nachher (mapping-Format):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<img src="{{= $cCMSData.logo.url }}" alt="{{= $cCMSData.logo.alt }}">
```

Neu direkt verfügbar sind außerdem `width`, `height` und die responsiven Varianten unter `formats`, beispielsweise `$cFields.logo.formats.thumbnail.url`. Geben Sie diese Werte nur aus, wenn sie gefüllt sind: Fehlende Angaben stehen auf `null`, und es werden nicht für jeden Shop dieselben Formate erzeugt.

### Schritt 7: SEO-Felder aus `meta` lesen

**Wann nötig:** Wenn Ihr Template Meta-Title, Meta-Description, Robots oder die SEO-URL aus den strapi-Daten ausgibt. Die Beispiele zeigen das schema-Format (zum mapping-Format siehe den Hinweis unter [Was Sie beim mapping-Format beachten müssen](#was-sie-beim-mapping-format-beachten-mussen)).

Diese Werte stammten bisher aus einer Inhalts-Komponente (beispielsweise „Meta Information") und stehen künftig im Bereich `meta` der Datei, mit neuen Feldnamen (siehe [Gegenüberstellung](#anderungen-gegenuber-der-alten-struktur)). Ersetzen Sie die bestehenden Zugriffe nach diesem Muster:

**Vorher (alte Struktur):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<title>{{= $cCMSData.attributes.MetaInformation.MetaTitle }}</title>
<meta name="description" content="{{= $cCMSData.attributes.MetaInformation.MetaDescription }}">
<meta name="robots" content="{{= $cCMSData.attributes.MetaInformation.MetaRobots }}">
```

**Nachher (schema-Format):**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<title>{{= $cCMSData.meta.metaTitle }}</title>
<meta name="description" content="{{= $cCMSData.meta.metaDescription }}">
<meta name="robots" content="{{= join($cCMSData.meta.robots, ",") }}">
```

Zwei Punkte fallen dabei besonders auf:

* **`robots` ist jetzt ein Array** und muss für die Ausgabe im Meta-Tag zu einem String zusammengefügt werden. `join` wird dafür mit Trennzeichen als Funktion aufgerufen; die Filter-Schreibweise `| join` in den Pfad-Beispielen dieser Seite fügt ohne Trennzeichen zusammen.
* **Die SEO-Felder stehen in `meta`, nicht in `fields`.** Das Name/Wert-Objekt `$cFields` aus Schritt 4 enthält sie nicht.

Neu verfügbar ist außerdem `meta.hreflang` mit einem Eintrag pro Subshop, der diese Sprache bedient. Wenn Sie hreflang-Tags ausgeben wollen, ist das die Datenbasis dafür.

### Schritt 8: Im Testmodus prüfen und live schalten

**Wann nötig:** Immer, als letzter Schritt.

Rufen Sie den Shop im Testmodus auf (siehe [Testmodi des Shops ein-/ausschalten](/testmodi-des-shops-ein-ausschalten)) und prüfen Sie jede migrierte Seite.

*Screenshot: Shop im Testmodus mit einer migrierten Inhaltsseite.*

Prüfliste:

* Werden alle Inhaltsblöcke ausgegeben – und in der Reihenfolge, die der Redakteur in strapi gesetzt hat?
* Erscheinen alle Bilder inklusive der responsiven Formate, mit Alternativtexten?
* Stimmt die SEO-Ausgabe im HTML-Head: Meta-Title, Meta-Description, Robots?
* Sind die Seiten über ihre SEO-URLs erreichbar?
* Gibt es leere Stellen, an denen vorher Inhalt stand? Das ist der typische Hinweis auf einen Feldnamen, der nicht mehr passt.

Vergleichen Sie dazu am besten Testmodus- und Live-Ausgabe derselben Seite direkt nebeneinander.

Erst wenn alle Seiten geprüft sind, entfernen Sie die Weiche aus Schritt 2: Der Testmodus-Zweig wird zum regulären Code, der `{{ else }}`-Zweig mit dem alten Ladeaufruf und der alten Ausgabe entfällt.

## Wenn etwas nicht funktioniert

| **Symptom**                                            | **Wahrscheinliche Ursache**                                                                                                   | **Prüfen**                                                                                                                                                                                |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Die Seite bleibt komplett leer, kein Inhalt aus strapi | Die Datei wurde nicht gefunden oder nicht geladen. `$wsExternalData.load` gibt in diesem Fall `null` zurück.                  | Dateiname und `documentId` prüfen (Schritt 3). Zur Fehlerursache liefert `$wsExternalData.getLastError()` einen Code, siehe [\$wsExternalData](/frontend/referenz/module/wsexternaldata). |
| Einzelne Werte fehlen, der Rest der Seite steht        | Der Feldname im Template passt nicht mehr zum Feldnamen in strapi.                                                            | Im schema-Format die `name`-Werte in `fields` mit den Feldnamen im Template vergleichen.                                                                                                  |
| Ein Inhaltsblock wird nicht ausgegeben                 | Die Komponenten-Kennung wird noch über `__component` geprüft, oder die Komponente ist im Template nicht umgesetzt.            | Schritt 5, insbesondere den `{{ else }}`-Zweig für unbekannte Komponenten.                                                                                                                |
| Bilder fehlen oder haben keinen Alternativtext         | Es wird noch über den alten `data`/`attributes`-Wrapper bzw. über `alternativeText` zugegriffen.                              | Schritt 6.                                                                                                                                                                                |
| Robots-Tag enthält etwas wie `noindexnofollow`         | Das Array `meta.robots` wurde ohne Trennzeichen zusammengefügt.                                                               | Schritt 7.                                                                                                                                                                                |
| Tief verschachtelte Inhalte sind abgeschnitten         | `maxDepth` im Ladeaufruf ist zu klein, oder eine Relation wurde von der Sync-Middleware nicht mehr aufgelöst (`value: null`). | Ladeoptionen und Abschnitt [Komponenten und Relationen](#komponenten-und-relationen).                                                                                                     |

Für den Umstellungstermin Ihres Shops sowie für die Aktivierung der Formate und die Neuerzeugung der Dateien für Bestandsinhalte (Backfill) wenden Sie sich an Ihren WEBSALE Ansprechpartner.


## Related topics

- [Migration](/migration.md)
- [Migration WEBSALE V8s -> Neue Version](/migration/migration-websale-v8s-neue-version.md)
- [Konfiguration-Migration](/migration/migration-websale-v8s-neue-version/konfiguration-migration.md)
- [Template-Migration](/migration/migration-websale-v8s-neue-version/template-migration.md)
- [Komponenten & Sammlungen in strapi](/strapi-cms/komponenten-sammlungen-in-strapi.md)
