Strukturierte Daten nach Schema.org
Polski for WooCommerce gibt keine eigenen strukturierten Daten aus. WooCommerce liefert auf jeder Produktseite bereits einen Product-Graphen als JSON-LD, und das Plugin ergänzt diesen Graphen über den Filter woocommerce_structured_data_product.
Das ist eine bewusste Entscheidung: zwei Product-Graphen auf einer Seite sind ein Duplikatfehler, und Suchmaschinen behandeln sie ohnehin als einen. Alles Folgende ist also eine Ergänzung der WooCommerce-Ausgabe, niemals ein Ersatz dafür.
Was woher kommt
Abschnitt betitelt „Was woher kommt“| Quelle | Felder |
|---|---|
| WooCommerce | name, description, image, sku, offers mit Preis, Währung, Verfügbarkeit und Zustand, aggregateRating und review |
| Polski for WooCommerce | brand, manufacturer, gtin8 / gtin12 / gtin13 / gtin14, additionalProperty mit dem Grundpreis, shippingDetails, nutrition |
| Polski for WooCommerce, im Angebot | priceValidUntil sowie der Omnibus-Tiefstpreis der letzten 30 Tage als priceSpecification |
Trägt eine Produktseite keine strukturierten Daten von WooCommerce, gibt es nichts zu ergänzen und das Plugin fügt nichts hinzu. Das ist wichtig, wenn ein SEO-Plugin den WooCommerce-Graphen durch einen eigenen ersetzt, siehe SEO-Plugins weiter unten.
Ein- und ausschalten
Abschnitt betitelt „Ein- und ausschalten“Die Ergänzungen im ersten Block sind doppelt abgesichert: das Modul Strukturierte Daten (Schema.org) muss aktiv sein, und darin der Schalter Integration strukturierter Daten aktivieren. Wird eines von beiden ausgeschaltet, bleibt der Graph von WooCommerce unberührt und vollständig.
| Einstellung | Optionsschlüssel | Standard | Steuert |
|---|---|---|---|
| Integration strukturierter Daten aktivieren | polski_seo[schema_enabled] |
an | Alles in der Tabelle unten |
| Marke einbeziehen | polski_seo[schema_brand] |
an | brand |
| Hersteller einbeziehen | polski_seo[schema_manufacturer] |
an | manufacturer |
| Barcodes (GTIN) einbeziehen | polski_seo[schema_gtin] |
an | gtin8 bis gtin14 |
| Grundpreis einbeziehen | polski_seo[schema_unit_price] |
an | additionalProperty |
Lieferzeit und Nährwerte haben keinen eigenen Schalter. Sie erscheinen, sobald das Produkt die Daten hat, und verschwinden, wenn nicht.
Die beiden Ergänzungen am Angebot laufen getrennt. priceValidUntil wird unabhängig vom Modul geschrieben, denn ein Angebot ohne dieses Feld verliert die Eignung für Rich Results, und es gibt keinen Grund, warum ein Shop das wollen sollte. Die Omnibus-Preisangabe folgt dem Modul Omnibus und erscheint nur, solange das Produkt tatsächlich reduziert ist.
Die Felder, die das Plugin hinzufügt
Abschnitt betitelt „Die Felder, die das Plugin hinzufügt“Marke und Hersteller
Abschnitt betitelt „Marke und Hersteller“{ "brand": { "@type": "Brand", "name": "MeineMarke" }, "manufacturer": { "@type": "Organization", "name": "Hersteller XYZ Sp. z o.o.", "contactPoint": { "@type": "ContactPoint", "contactType": "product safety", } }}brand ist die erste für das Produkt gefundene Marke. manufacturer beginnt beim Herstellernamen aus dem Produktpanel; ein am Produkt hinterlegter GPSR-Herstellername ersetzt ihn und ergänzt den GPSR-Kontakt als contactPoint vom Typ product safety. Die Anschrift wird nicht veröffentlicht, der Kontakttext genau so ausgegeben, wie Sie ihn eingetragen haben.
Der Barcode aus dem Produktpanel wird unter dem Schlüssel veröffentlicht, der zu seiner Länge passt: 8 Ziffern werden zu gtin8, 12 zu gtin12, 13 zu gtin13, 14 zu gtin14. Jede andere Länge erscheint als einfaches gtin, was gültiges Schema.org ist, Google aber weniger sagt.
Grundpreis
Abschnitt betitelt „Grundpreis“Schema.org kennt keine Eigenschaft für den Grundpreis, also reist die Angabe in additionalProperty mit:
{ "additionalProperty": [ { "@type": "PropertyValue", "name": "Grundpreis", "value": "8.90 / 100 g" } ]}Lieferzeit
Abschnitt betitelt „Lieferzeit“Ergibt sich für das Produkt eine Lieferzeit, wird ein OfferShippingDetails-Block ergänzt:
{ "shippingDetails": { "@type": "OfferShippingDetails", "deliveryTime": { "@type": "ShippingDeliveryTime", "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" }, "transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" } }, "shippingDestination": { "@type": "DefinedRegion", "addressCountry": "PL" } }}Zwei Grenzen sollten Sie kennen, bevor Sie sich darauf verlassen. Die Bearbeitungszeit steht fest auf 0 bis 1 Tag und wird nicht aus Ihren Einstellungen gelesen, und die obere Transportzeit stammt aus den Ziffern in Ihrem Lieferzeit-Text, mit 5 Tagen als Rückfall, wenn der Text keine enthält. Eine als „2 bis 3 Werktage” geschriebene Lieferzeit ergibt daher eine obere Transportzeit von 23. Halten Sie den Text auf einer einzigen Zahl, wenn die Angabe für Sie zählt.
Zielland ist Polen.
Nährwerte
Abschnitt betitelt „Nährwerte“Produkte mit Nährwertdaten aus dem Lebensmittelmodul erhalten ein NutritionInformation-Objekt:
| Gespeicherter Nährwert | Schema.org-Feld |
|---|---|
| Energie (kcal) | calories |
| Fett | fatContent |
| davon gesättigte Fettsäuren | saturatedFatContent |
| Kohlenhydrate | carbohydrateContent |
| davon Zucker | sugarContent |
| Eiweiß | proteinContent |
| Ballaststoffe | fiberContent |
| Salz | sodiumContent, umgerechnet |
Die letzte Zeile ist die, die man zweimal lesen sollte. Anhang XV der Verordnung 1169/2011 deklariert Salz, Schema.org bietet nur sodiumContent, und beides ist nicht dieselbe Zahl: Salz ist Natrium mal 2,5. Der Wert wird vor der Veröffentlichung durch 2,5 geteilt, ein mit 2,5 g Salz ausgezeichnetes Produkt veröffentlicht also 1 g Natrium. Bis 1.36.7 wurde die Zahl unverändert übernommen, wodurch jedes Lebensmittel zweieinhalbmal so salzig veröffentlicht wurde, wie sein eigenes Etikett angibt.
Energie in kJ hat keine Entsprechung in Schema.org und wird nicht veröffentlicht. In der Tabelle auf der Produktseite erscheint sie weiterhin, dort verlangt die Verordnung sie.
priceValidUntil und der Omnibus-Preis
Abschnitt betitelt „priceValidUntil und der Omnibus-Preis“{ "offers": [ { "priceValidUntil": "2026-12-31", "priceSpecification": { "@type": "UnitPriceSpecification", "priceType": "https://schema.org/MinimumPrice", "name": "Niedrigster Preis der letzten 30 Tage", "price": "79.00", "priceCurrency": "PLN" } } ]}priceValidUntil nimmt das Ende des Angebotszeitraums, sofern das Produkt eines hat, sonst ein Jahr ab heute. Geschrieben wird das Feld nur, wenn WooCommerce es leer gelassen hat.
Die priceSpecification trägt den niedrigsten Preis der vorangegangenen 30 Tage. Es ist dieselbe Zahl, die Kundinnen und Kunden unter dem Preis sehen, veröffentlicht in einer Form, die eine Suchmaschine oder ein Assistent zitieren kann, und sie erscheint nur, solange das Produkt reduziert und das Omnibus-Modul aktiv ist.
Zwischenspeicherung
Abschnitt betitelt „Zwischenspeicherung“Die ergänzten Felder werden je Produkt 12 Stunden lang in einem Transient polski_schema_<id> gehalten, und der Transient wird bei jedem Speichern des Produkts gelöscht.
Eine Folge davon: Das Umlegen der obigen Schalter leert den Cache nicht. Ein bestehendes Produkt behält seine bisherigen Felder bis zu 12 Stunden oder bis es gespeichert wird. Speichern Sie das Produkt, um eine Einstellungsänderung sofort zu sehen.
Erweitern
Abschnitt betitelt „Erweitern“Das Plugin stellt für strukturierte Daten keine eigenen Filter bereit. Verwenden Sie den Filter von WooCommerce, mit einer Priorität über 10, damit Ihr Callback nach dem des Plugins läuft:
add_filter( 'woocommerce_structured_data_product', function ( array $markup, WC_Product $product ): array { $markup['award'] = 'Produkt des Jahres 2025';
if ( isset( $markup['offers'][0] ) ) { $markup['offers'][0]['warranty'] = [ '@type' => 'WarrantyPromise', 'durationOfWarranty' => [ '@type' => 'QuantitativeValue', 'value' => 24, 'unitCode' => 'MON', ], ]; }
return $markup;}, 20, 2 );Um ein vom Plugin ergänztes Feld zu entfernen, löschen Sie es im selben Callback. Damit das Plugin gar nichts mehr ergänzt, nehmen Sie die Schalter statt Code.
SEO-Plugins
Abschnitt betitelt „SEO-Plugins“Es gibt keine Erkennung und kein plugin-spezifisches Verhalten. Alles hängt davon ab, was das SEO-Plugin mit dem Graphen von WooCommerce macht:
- Es lässt die strukturierten Daten von WooCommerce stehen. Die Ergänzungen erscheinen wie beschrieben.
- Es ersetzt die strukturierten Daten von WooCommerce durch einen eigenen Graphen. Es wird nichts ergänzt, weil der Filter nie läuft. Mehrere SEO-Plugins haben genau dafür einen Schalter; aktivieren Sie dort die WooCommerce-Daten wieder, oder verlagern Sie die benötigten Felder in den Graphen jenes Plugins. Welches davon sie entfernt und ob standardmäßig, ändert sich zwischen deren Versionen, prüfen Sie also den Quelltext Ihrer eigenen Seite statt einer Liste.
Sehen Sie im Quelltext zwei Product-Blöcke, stammt der zweite nicht von diesem Plugin. Suchen Sie im SEO-Plugin oder im Theme.
Das Plugin protokolliert nichts zu strukturierten Daten, ein leeres debug.log sagt also in keine Richtung etwas aus. Lesen Sie den Quelltext der Seite oder nutzen Sie die beiden Werkzeuge oben.
Fehlersuche
Abschnitt betitelt „Fehlersuche“Überhaupt keine ergänzten Felder. Prüfen Sie, ob die strukturierten Daten von WooCommerce auf der Seite stehen. Gibt es keinen Product-Block, hatte der Filter nichts, worauf er laufen konnte.
Ein Feld fehlt weiterhin, obwohl ich es ausgefüllt habe. Das Produkt muss die Daten haben, der passende Schalter muss an sein, und danach muss das Produkt gespeichert werden, um den 12-Stunden-Cache zu leeren.
Keine Bewertungen. aggregateRating kommt von WooCommerce, nicht von diesem Plugin, und braucht mindestens eine Rezension mit Sternebewertung.
Google zeigt keine Rich Results. Rich Results folgen der Neuindexierung, das dauert Wochen. Erst validieren, dann warten.
Probleme melden: github.com/wppoland/polski/issues