Wichtigste Erkenntnisse
- CLS bei Shopify misst unerwartete Layout-Verschiebungen. Jede Verschiebung wird aus der Impact Fraction multipliziert mit der Distance Fraction berechnet, und dein CLS ist die schlimmste Häufung (Burst) von Verschiebungen auf der Seite, nicht die Gesamtsumme.
- Googles Grenzwerte sind 0.1 oder weniger für “Gut” und über 0.25 für “Schlecht”, gemessen am 75. Perzentil echter Seitenaufrufe.
- Der Lab-CLS sieht oft gut aus, während CrUX ihn als schlecht einstuft, da ein Lab-Test nur die Verschiebungen während seines eigenen Seitenaufbaus bei einem festen Viewport erfasst.
- Die meisten Shopify-CLS-Probleme lassen sich auf eine kurze Liste zurückführen: Bilder ohne Dimensionen, Webfonts, Announcement Bars, Sticky Headers und von Apps eingefügte Widgets “above the fold”.
- CrUX ist ein gleitender 28-Tage-Durchschnitt, ein veröffentlichter Fix braucht also bis zu vier Wochen, um sich vollständig in den Felddaten von PageSpeed Insights niederzuschlagen.
CLS bei Shopify ist die Metrik, die dich für Inhalte bestraft, die sich bewegen, nachdem die Seite bereits gerendert wird. Der Shopper will auf den “In den Warenkorb”-Button klicken, ein Review-Widget lädt darüber, und der Klick landet ganz woanders.
Dieser Guide behandelt, wie der Score tatsächlich berechnet wird, wie man das verschiebende Element findet, anstatt nur zu raten, und welche spezifischen Shopify-Ursachen man zuerst prüfen sollte. Die Diagnose-Hälfte gilt für jede Website. Die Fixes sind auf Theme- und Liquid-Ebene.
Warum du uns vertrauen kannst
Wir sind seit über vier Jahren im Shopify-Bereich tätig und haben mit Hunderten von Shopify-Marken an ihren Storefronts gearbeitet. Jacques hat über 15 Jahre Entwicklungserfahrung. Wir entwickeln Fudge, einen KI-Storefront-Editor mit einer 5,0-Bewertung im Shopify App Store und „Built for Shopify“-Status. Wir arbeiten also genau an der Theme-Ebene, auf der der Layout Shift entsteht.
Was misst CLS und wie wird der Score berechnet?
CLS misst den größten Burst an unerwarteten Layout-Verschiebungen, der während des gesamten Lebenszyklus einer Seite auftritt.1
Zwei Wörter in dieser Definition sind entscheidend.
“Unerwartet.” Eine Verschiebung, die innerhalb von 500 Millisekunden nach einer diskreten Benutzereingabe (wie einem Tippen, Klicken oder Tastendruck) auftritt, erhält das Flag hadRecentInput und wird ausgeschlossen.1 Scrollen, Ziehen und Pinch-to-Zoom zählen nicht als kürzliche Eingabe, daher wird eine Verschiebung beim Scrollen weiterhin gewertet.
“Größter Burst.” CLS ist nicht die Summe jeder einzelnen Verschiebung auf der Seite. Verschiebungen werden in Session-Fenstern gruppiert: Ein Burst von Verschiebungen, die jeweils weniger als eine Sekunde auseinanderliegen, mit einem maximalen Gesamtfenster von fünf Sekunden.1 Dein CLS ist das Fenster mit dem höchsten Score.
Impact Fraction und Distance Fraction
Jede einzelne Verschiebung wird wie folgt berechnet:
Layout Shift Score = Impact Fraction x Distance Fraction
Impact Fraction (Auswirkungsanteil) ist die kombinierte sichtbare Fläche aller instabilen Elemente im aktuellen und vorherigen Frame im Verhältnis zur Gesamtfläche des Viewports.1
Distance Fraction (Entfernungsanteil) ist die größte Distanz, die ein instabiles Element in diesem Frame zurückgelegt hat, geteilt durch die größte Dimension des Viewports.1
Die praktische Konsequenz: Ein kleines Element, das sich weit bewegt, und ein großes Element, das sich nur ein kurzes Stück bewegt, können denselben Score erzielen. Ein Hero-Banner in voller Breite, das auf dem Smartphone um 100px nach unten gedrückt wird, ist teuer, weil die Impact Fraction nahe bei 1 liegt.
Was ist ein guter CLS-Score im Jahr 2026?
| Score | Bewertung |
|---|---|
| 0.1 oder weniger | Gut |
| Über 0.1 bis 0.25 | Verbesserungsbedürftig |
| Über 0.25 | Schlecht |
Die Grenzwerte werden am 75. Perzentil der Seitenaufrufe bewertet, getrennt für Mobile und Desktop.1 Dein medianer Besucher kann eine saubere Experience haben, während du trotzdem durchfällst, weil das langsamste Viertel der Ladevorgänge die Note bestimmt.
Google gibt an, dass die Core Web Vitals mit dem übereinstimmen, was ihre Core-Ranking-Systeme belohnen, und nennt 0.1 als CLS-Ziel.2 Es ist jedoch nur ein Signal von vielen, kein Ein-/Aus-Schalter. Für ein breiteres Bild, wo Shopify-Stores derzeit stehen, siehe unseren Bericht zum Stand der Shopify-Performance.
Warum sieht der Labor-CLS gut aus, wenn CrUX ihn als schlecht einstuft?
Das ist die häufigste Verwirrung, und es ist kein Bug in einem der Tools.
Labordaten basieren auf einem einzelnen synthetischen Ladevorgang: ein emuliertes Gerät, ein Viewport, ein kalter Cache, kein Scrollen, keine Interaktion. Lighthouse meldet den Shift, den es während dieses Traces sieht, und stoppt dann.
Felddaten stammen von CrUX und werden von echten Chrome-Nutzern über den gesamten Lebenszyklus der Seite aggregiert. Sie beinhalten Shifts, die passieren, wenn jemand zu den Bewertungen scrollt, eine Variante wechselt oder bei einer langsamen Verbindung wartet, bis ein App-Widget geladen ist.
Vier Lücken verursachen diese Diskrepanz:
- Timing. Bei einer schnellen Laborverbindung landet ein spätes Skript vor dem First Paint und verschiebt nichts. Bei echtem 4G landet es danach.
- Interaktion. Lab-Tests scrollen nie, sodass eine Collection-Seite, die beim Lazy-Load springt, perfekt aussieht.
- Viewport-Verteilung. Ein Banner, das bei 360px auf zwei Zeilen umbricht, verschiebt alles darunter.
- Geografie. Währungsrechner und geolokalisierte Banner feuern nur bei bestimmten Besuchern.
Wenn das Labor 0 und das Feld 0,3 anzeigt, vertraue den Felddaten und suche nach Interaktions- und Scroll-Shifts.
So diagnostizierst du CLS in einem Shopify-Store
Arbeite zuerst mit Felddaten (Field Data), dann reproduziere es lokal.
1. Lies die Felddaten. Lass die Live-URL durch PageSpeed Insights laufen und lies den CrUX-Bereich oben, nicht den Lighthouse-Score darunter. Prüfe Mobile und Desktop, und teste eine Produktseite, eine Collection-Page und die Homepage separat. Der Core Web Vitals-Bericht in der Search Console gruppiert ähnliche URLs, was dir sagt, ob das Problem nur bei einem Template oder im gesamten Theme besteht.
2. Zeichne einen Trace auf. Drossele im Performance-Panel der Chrome DevTools die Verbindung auf “Slow 3G” und die CPU auf 4x (Slowdown), und zeichne dann einen Reload auf. Der “Layout Shifts”-Track füllt sich mit lila Balken. Klicke auf eine einzelne Verschiebung, um das Element, das sich bewegt hat, sowie einen Vorher-Nachher-Screenshot zu sehen. Der Insight “Layout shift culprits” hebt den schlimmsten Cluster hervor und liefert eine gute Vermutung zur Ursache.
3. Aktiviere das Overlay. Öffne in den DevTools die Settings, dann “More tools”, dann “Rendering” und setze einen Haken bei Layout Shift Regions. Verschiebende Bereiche blinken lila, wenn sie sich bewegen.3 Das ist der schnellste Weg, um Shifts zu erwischen, die du sonst übersehen würdest.
4. Jage die Interaktions-Shifts. Lab-Tests finden diese nicht, also löse sie manuell aus, während die Live-Metriken im Performance-Panel geöffnet sind: Scrolle die komplette Seite, wechsle Produktvarianten, öffne den Cart Drawer, ändere die Währung, wende einen Filter auf der Collection-Page an. Beobachte, wie der CLS-Wert klettert, und notiere dir, was du gerade gemacht hast.
5. Überwache das Feld. Logge echte Shifts für Probleme, die du nicht reproduzieren kannst. Die Layout Instability API liefert dir die schuldigen Nodes in entry.sources:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log(
entry.value,
entry.sources.map((s) => s.node),
)
}
}
}).observe({type: 'layout-shift', buffered: true})
Jede Quelle enthält previousRect und currentRect, sodass du genau sehen kannst, wie weit sich ein Node bewegt hat. Beachte, dass das Element, das sich bewegt hat, normalerweise das Opfer ist, nicht der Täter. Der Täter ist das, was darüber aufgetaucht ist.
Shopify-spezifische CLS-Ursachen und deren Lösungen
| Ursache | Fix |
|---|---|
| Bilder oder Videos ohne Dimensionen | width und height Attribute oder aspect-ratio auf dem Wrapper |
| Webfont Swap | font-display, Preload der Font-Datei, Fallback mit angepassten Metriken |
| Announcement- oder Free-Shipping-Bar | Serverseitig in Liquid rendern oder min-height reservieren |
| Cookie-Banner | Fixed Overlay außerhalb des Document Flows |
| App-Widgets (Reviews, Währung, Upsell) | App-Blöcke plus ein Container mit reservierter min-height |
| Lazy-Loaded Content “above the fold” | loading="eager" und fetchpriority="high" auf dem Hero-Bild |
| Sticky Header | position: sticky oder ein Spacer, der der Header-Höhe entspricht |
| Variantenwechsel | Festes aspect-ratio auf dem Product-Media-Wrapper |
| Infinite Scroll | Skeleton-Placeholders oder ein “Load more”-Button |
| Spät eintreffendes Section-CSS | Above-the-fold-CSS synchron laden |
Bilder und Videos ohne Abmessungen
Setze width und height, damit der Browser die Box reserviert, bevor die Datei ankommt, und lass dann CSS das Responsive Design übernehmen:
<img src="hero.jpg" width="1600" height="900" alt="Autumn collection" />
img {
width: 100%;
height: auto;
}
In Liquid gibt der image_tag-Filter automatisch width und height für dich aus, berechnet aus dem Quellbild:
{{ product.featured_image | image_tag: widths: '400, 800, 1200', sizes: '(min-width: 750px) 50vw, 100vw' }}
Für Videos, Embeds und alles ohne intrinsische Größe reservierst du die Box auf dem Wrapper:
.video-wrapper {
aspect-ratio: 16 / 9;
}
Webfonts und der Swap-Shift
Ein Custom Font lädt, ersetzt den Fallback, und jede Textzeile wird neu gemessen. Wenn die beiden Fonts unterschiedliche Metriken haben, ändert sich die Höhe des Blocks und schiebt den Inhalt nach unten.
Drei Fixes, sortiert nach Aufwand:
Setze font-display. Shopifys font_face-Filter nimmt den Parameter direkt an:
{{ settings.type_body_font | font_face: font_display: 'swap' }}
swap zeigt den Fallback sofort und tauscht ihn dann aus. Der Text ist also immer sichtbar, aber der Shift passiert trotzdem. optional vermeidet den Shift komplett, indem es auf den Tausch verzichtet, wenn die Schriftart langsam ist – auf Kosten dessen, dass einige Besucher deine Marken-Schriftart nie sehen.
Preloade die Datei, damit der Swap vor dem First Paint passiert und nicht danach:
<link rel="preload" href="{{ settings.type_body_font | font_url }}" as="font" type="font/woff2" crossorigin>
Gleiche die Fallback-Metriken an (Match metrics). Das entfernt den Shift, ohne auf die Schriftart verzichten zu müssen. Deklariere einen lokalen Fallback mit Overrides, die auf deinen Webfont abgestimmt sind, und liste ihn im Stack auf:
@font-face {
font-family: 'Body Fallback';
src: local('Arial');
size-adjust: 103%;
ascent-override: 92%;
descent-override: 24%;
line-gap-override: 0%;
}
body {
font-family: 'Your Font', 'Body Fallback', sans-serif;
}
Die Prozentzahlen sind spezifisch für jedes Font-Paar. Miss sie selbst, anstatt diese hier einfach zu kopieren.
Announcement Bars, Cookie-Banner und Shipping Bars
Alles, was “above the fold” injiziert wird, drückt die gesamte Seite nach unten, was eine Impact Fraction von fast 1 bedeutet.
Rendere es in Liquid. Eine Bar, die im serverseitig gerenderten HTML ausgeliefert wird, verschiebt niemals etwas, da sie vom ersten Frame an da war. Das ist in fast jedem Fall der beste Fix.
Wenn es JavaScript sein muss, reserviere die Höhe, bevor es gerendert wird:
.announcement-bar {
min-height: 40px;
}
Setze denselben Wert auf dem Platzhalter für jeden Breakpoint, bei dem der Text in eine zweite Zeile umbricht. Eine Reservierung von 40px für eine Bar, die auf einem 360px-Bildschirm mit 72px gerendert wird, ist immer noch ein Shift.
Cookie-Banner gehören nicht in den Document Flow. Nutze position: fixed, damit der Banner über dem Inhalt liegt, anstatt ihn zu verdrängen.
Von Apps injizierter Content
Review-Widgets, Währungsrechner, Upsell-Blöcke, Größentabellen und Chat-Bubbles laden alle spät und breiten sich im Layout aus.
Bevorzuge App-Blöcke (App Blocks), die über den Theme-Editor hinzugefügt werden. Sie rendern innerhalb der Section, im Document Flow, bereits zur Server-Render-Zeit. Legacy-Widgets, die per Skript injiziert werden, kommen erst nach dem Paint an und verschieben alles, was darunter liegt.
Wo die App trotzdem noch spät injiziert wird, reserviere den Container:
.shopify-app-block {
min-height: 24px;
}
.product-reviews-placeholder {
min-height: 180px;
}
Chat-Bubbles sollten position: fixed sein, niemals im Document Flow. Für eine Anleitung, wie du herausfindest, welche App verantwortlich ist, siehe unseren Guide zur Behebung von Layout-Problemen nach der Installation von Shopify-Apps.
Lazy-Loaded Content above the fold
loading="lazy" auf einem Hero-Bild ist ein selbstverschuldeter Shift. Der Browser zögert den Fetch hinaus, der Platz bleibt während des kritischen Zeitfensters leer und der Inhalt platziert sich zu spät.
Gib dem ersten Viewport “Eager Loading” und eine hohe Fetch Priority:
<img src="hero.jpg" width="1600" height="900" loading="eager" fetchpriority="high" alt="Hero" />
Alle Details dazu findest du in unserem Guide zum Shopify Hero Banner Eager Loading Fix.
Das Gleiche gilt für Sections, die durch JavaScript eingeblendet werden. Fade-In-Animationen, die height, top oder margin animieren, werden in jedem Frame als Layout Shifts registriert. Animiere stattdessen transform und opacity, was der Compositor ohne Reflow verarbeiten kann.
Sticky Headers
Ein Header, der beim Scrollen auf position: fixed wechselt, verlässt den Dokumentenfluss, und die darunterliegende Seite klappt um die Höhe des Headers nach oben.
Verwende stattdessen position: sticky, was den Platz des Elements reserviert. Wenn das Design fixed benötigt, füge in dem Moment, in dem die Klasse wechselt, ein Spacer-Element in gleicher Höhe ein und halte beide mit einer CSS Custom Property synchron.
Variantenwechsel auf Produktseiten
Hier gibt es zwei Shift-Quellen.
Unterschiedliche Bilddimensionen. Ein hochformatiges Variantenbild, das ein quadratisches ersetzt, verändert die Höhe des Media-Blocks. Sperre den Wrapper ein:
.product-media {
aspect-ratio: 1 / 1;
}
.product-media img {
width: 100%;
height: 100%;
object-fit: contain;
}
Section Rendering API Swaps. Das Neu-Rendern des Produktformulars beim Variantenwechsel ersetzt Markup durch Markup mit einer anderen Höhe – meistens, weil ein Sale-Badge, ein Inventar-Hinweis oder ein Abo-Selector für eine Variante erscheint und für eine andere nicht. Reserviere eine min-height auf dem Bereich, der ausgetauscht wird.
Diese Shifts passieren oft innerhalb von 500ms nach einem Klick, daher werden sie häufig vom CLS ausgeschlossen. Sie schaden der Usability aber trotzdem, und jeder Folge-Reflow, der später ankommt, wird nicht ausgeschlossen.
Infinite Scroll auf Collection-Seiten
Das Anhängen von Produkten verschiebt den Footer und alles andere, was im Sichtfeld ist. Reserviere den Platz mit Skeleton-Placeholders, die an die echten Grid-Reihen angepasst sind, oder nutze einen “Load more”-Button, der den Shift benutzerinitiiert macht.
Bei langen Grids hilft “Size Containment” dem Browser, die Größe für Off-Screen-Reihen richtig zu schätzen:
.product-grid__item {
content-visibility: auto;
contain-intrinsic-size: auto 420px;
}
Spät ladendes CSS
Asynchron geladene Section-Stylesheets stylen Content neu, der bereits gemalt (painted) wurde. Lade das CSS für Above-the-fold-Sektionen normal und verzögere nur das, was darunter liegt. Unser Guide über Render-Blocking Scripts in Shopify behandelt, wo hier die Grenze liegt.
Wo Fudge ins Spiel kommt
Die meisten der oben genannten Fixes sind kleine, gezielte Änderungen an Liquid, CSS und Theme-JavaScript. Fudge schreibt diese Änderungen als nativen Theme-Code, anstatt eine weitere Ebene über deinen Store zu legen.
Bitte um eine reservierte Höhe in der Announcement Bar oder eine feste Aspect Ratio für den Produkt-Media-Wrapper, und die Änderung landet direkt in den Theme-Dateien. Kein zusätzliches Skript, kein Widget – was wichtig ist, wenn die Metrik, die du verbessern willst, durch zusätzliche Skripte und Widgets verursacht wird. Das Gleiche gilt für alles andere, was mit dem Shopify Store Editor erstellt wurde: Entferne Fudge, und der Code bleibt.
So überprüfst du den Fix und wann CrUX nachzieht
Die Überprüfung läuft in drei Phasen ab, und die letzte ist langsam.
Sofort: neu aufnehmen. Zeichne die Seite im Performance-Panel mit demselben Throttling nochmal auf. Der Layout-Shifts-Track sollte leer sein oder nah dran. Wiederhole das Ganze mit aktivierten Layout Shift Regions, scrolle die komplette Seite und wechsle Varianten.
Innerhalb eines Tages: Labor checken. Lass PageSpeed Insights über die Live-URL laufen. Labor-CLS bestätigt, dass die Verschiebungen zur Ladezeit behoben sind, sagt aber nichts über Interaktions-Shifts aus, also höre hier nicht auf.
Über 28 Tage: Das Feld beobachten. CrUX ist ein gleitender 28-Tage-Durchschnitt, der täglich gegen 04:00 UTC aktualisiert wird.4 Am Tag nach deiner Live-Schaltung enthalten 27 der 28 Tage immer noch die fehlerhafte Seite. Verbesserungen zeigen sich allmählich und erreichen ihren wahren Wert erst etwa vier Wochen nachdem der Fix für den gesamten Traffic live ist.
Zwei Dinge bereiten den Leuten hier oft Probleme. Der Fix muss im Live-Theme veröffentlicht sein, da CrUX nur echte Besucher beobachtet. Und eine URL braucht genug Traffic, um überhaupt gemeldet zu werden – schwach besuchte Seiten zeigen möglicherweise immer nur Daten auf Origin-Ebene.
Sobald der CLS sitzt, gilt derselbe Loop für den Rest der Vitals. Unser Guide dazu, wie man ein Shopify-Theme schneller macht, deckt die Ladezeit-Seite ab.
FAQ
0.1 oder weniger ist gut, über 0.1 bis 0.25 ist verbesserungsbedürftig und über 0.25 ist schlecht. Google bewertet dies am 75. Perzentil realer Seitenaufrufe, getrennt nach Mobile und Desktop. Das bedeutet, dass ein Viertel deiner Besucher den Grenzwert überschreiten und dir den Score ruinieren kann, weshalb Mobile meistens die wichtigere Zahl ist.
Ein Lab-Test ist ein synthetischer Ladevorgang auf einem emulierten Gerät, ohne Scrollen und ohne Interaktion. Er sieht also nur Shifts, die während dieses Traces passieren. CrUX-Felddaten stammen von echten Chrome-Nutzern über den gesamten Lebenszyklus der Seite, einschließlich Shifts, die durch Scrollen, Variantenwechsel und App-Skripte (die bei langsamen Verbindungen spät eintreffen) ausgelöst werden. Wenn beide voneinander abweichen, vertraue den Felddaten und suche gezielt nach Interaktions- und Scroll-Shifts.
Häufig. Review-Widgets, Währungsrechner, Upsell-Blöcke und Chat-Bubbles injizieren Inhalte, nachdem die Seite gepaintet wurde, und schieben alles darunterliegende nach unten. App-Blöcke, die über den Theme-Editor hinzugefügt werden, sind sicherer, da sie zur Server-Render-Zeit im Document Flow gerendert werden. Für per Skript injizierte Widgets solltest du den Platz mit einer min-height auf dem Container reservieren.
Zeichne einen Trace im Performance-Panel der Chrome DevTools mit aktivierter Drosselung auf und klicke dann auf einzelne Shifts im "Layout Shifts"-Track, um das Element und einen Vorher-Nachher-Screenshot zu sehen. Wenn du "Layout Shift Regions" im Rendering-Tab aktivierst, blinken verschiebende Bereiche in Echtzeit lila. Denke daran, dass das Element, das sich bewegt hat, meistens das Opfer ist und der Täter das ist, was darüber aufgetaucht ist.
CrUX ist ein gleitender 28-Tage-Durchschnitt, der täglich aktualisiert wird. Verbesserungen erscheinen also allmählich und nicht über Nacht. Rechne mit etwa vier Wochen, nachdem der Fix im veröffentlichten Theme live ist, bis der Feld-Score seinen wahren Wert widerspiegelt. Lab-Tools bestätigen den Fix sofort, erfassen aber nur Shifts während der Ladezeit.
Ja, wenn sie durch JavaScript injiziert anstatt in Liquid gerendert wird, da sie dann über allem anderen erscheint und die gesamte Seite nach unten drückt. Wenn die Bar serverseitig im Theme gerendert wird, verschwindet der Shift komplett. Wenn sie dynamisch sein muss, setze eine min-height auf ihren Container, die der gerenderten Höhe bei jedem Breakpoint entspricht – auch bei denen, wo der Text zweizeilig umbricht.
Google gibt an, dass die Core Web Vitals mit dem übereinstimmen, was ihre Core-Ranking-Systeme belohnen, und nennt einen CLS unter 0.1 als Ziel. Es ist jedoch eher ein Signal von vielen als ein alles entscheidendes. Das stärkere Argument ist meist die Usability: Eine Seite, die sich unter dem Daumen des Shoppers bewegt, führt zu Fehlklicks auf den "In den Warenkorb"-Button.
Footnotes
-
web.dev, “Cumulative Layout Shift (CLS)” – Definition, die Formel “Impact Fraction mal Distance Fraction”, die Ein-Sekunden-Lücke und das maximale Fünf-Sekunden-Session-Fenster, der 500ms
hadRecentInput-Ausschluss und die 0.1 / 0.25-Grenzwerte am 75. Perzentil. https://web.dev/articles/cls ↩ ↩2 ↩3 ↩4 ↩5 ↩6 -
Google Search Central, “Understanding Core Web Vitals and Google search results” – gibt an, dass die Page Experience mit dem übereinstimmt, was Core-Ranking-Systeme belohnen, und nennt 0.1 als CLS-Ziel. https://developers.google.com/search/docs/appearance/core-web-vitals ↩
-
Chrome for Developers, “Discover issues with rendering performance” – die Option “Layout Shift Regions” im Rendering-Tab hebt verschiebende Bereiche kurz lila hervor. https://developer.chrome.com/docs/devtools/rendering/performance ↩
-
Chrome for Developers, “CrUX API” – der Chrome UX Report ist ein gleitender 28-Tage-Durchschnitt aggregierter Metriken, der täglich um ca. 04:00 Uhr UTC aktualisiert wird. https://developer.chrome.com/docs/crux/api ↩