=== NeoSEO ===
Contributors: mtpamir
Tags: product schema, merchant listings, woocommerce schema, rich results, structured data
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 7.4
WC tested up to: 11.1
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Product schema for WooCommerce: variants as ProductGroup, shipping and returns from your settings, the data Google's merchant listings check for.

== Description ==

NeoSEO is a free WooCommerce product schema plugin. It gives Google the structured data its **Merchant listings** and **Product snippets** reports check for: every variant of a variable product, shipping details from your real shipping zones, and the return policy you declare. Everything runs on your own store. No account, no API key, and nothing is sent anywhere.

If Search Console has emailed you "Merchant listings structured data issues detected", or flagged `Missing field "shippingDetails"` or `Missing field "hasMerchantReturnPolicy"`, those are the fields NeoSEO fills in, from data WooCommerce already holds.

**Compatible with 233 of the most popular WooCommerce themes**, 195 out of the box and 38 with one setting, including Storefront, Twenty Twenty-Five, Astra, Kadence, OceanWP, Blocksy, GeneratePress and Hello Elementor, and with shops built in Elementor, Elementor Pro and Divi. Each was checked over HTTP on a real store. [See the full theme compatibility list](https://neoplugin.com/product/neoseo-theme-compatibility).

**Works beside the SEO plugin you already use.** When Yoast, Rank Math, All in One SEO, SEOPress, Slim SEO, The SEO Framework, Squirrly or WPSSO is active, NeoSEO switches its overlapping modules off by itself.

### What changes on your store

Activate it and these appear by themselves. Nothing to paste in, no block to place, no shortcode to find:

* **Product pages**: a Product node in the page head, or a ProductGroup with every variation for a variable product. It carries offers, shipping, returns, brand, GTIN, ratings and reviews.
* **Shop and category pages**: an ItemList of the products the page actually shows.
* **Every page**: Organization, WebSite, WebPage and breadcrumb nodes, linked into one graph, plus meta description, Open Graph and Twitter tags when no SEO plugin is writing them.
* **Blog posts**: BlogPosting markup with `speakable` hints, and a FAQPage built from core Details blocks.
* **`/llms.txt`**: a markdown summary of your site for AI crawlers, kept current as you publish.
* **In the admin**: a Dashboard showing how much of your catalogue carries schema, a schema inspector, and a Search Appearance box on the product editor with a live search-result preview.

Shoppers see no difference. NeoSEO adds no script and no stylesheet to your storefront, and nothing on the visible page changes.

### What it does for your search results

**1. It keeps the rich result.**
One missing property does not shrink a product's rich result. It removes the whole thing, silently, with no warning in your dashboard. NeoSEO reads what WooCommerce already knows (variations, shipping zones, brands, dimensions, stock) and writes it as the structured data Google, Bing and AI answer engines read.

**2. It shows each variant as its own product.**
A variable product is not one purchasable thing. It is several, each with its own price, SKU, colour and availability. NeoSEO writes a `ProductGroup` with `hasVariant`, `variesBy` and `productGroupID`, and nests every variation inside it as a Product node with its own SKU, GTIN, image, price, stock and condition. Colour, size, material and pattern are read from your own attributes, in your own language. An `AggregateOffer` sits alongside, so the price range still reads correctly.

**3. It takes shipping and returns from your settings.**
Google increasingly wants both before it shows a product with its price and availability. `shippingDetails` comes from your live shipping zones: each zone's destination and its cheapest fixed rate, with unconditional free shipping as a zero rate. `hasMerchantReturnPolicy` comes from a short Returns form on the settings screen.

**4. It never invents a field.**
A shipping cost worked out by a formula, free shipping that needs a minimum order, or a return policy you have not filled in is left out rather than guessed at. Markup that disagrees with your checkout is worse than none.

*More on what these reports check and how to fix each warning: [NeoSEO on neoplugin.com](https://neoplugin.com/product/neoseo).*

### Why NeoSEO beside the plugin you already use

**It stands aside where another plugin covers the job.**
NeoSEO is not a replacement for your SEO plugin. When one of the full SEO plugins above is active, every overlapping module switches itself off.

**It tells you when two plugins write the same markup.**
NeoSEO also detects structured-data-only plugins, such as Schema & Structured Data for WP & AMP and Schema Pro. It switches its own schema module off beside them, and says so plainly when two plugins are both writing Product markup, the most common reason rich results get ignored.

**Variant markup stays on, on purpose.**
The free versions of the major SEO plugins do not write variant markup, so NeoSEO's variant module keeps running beside them. Beside Yoast WooCommerce SEO or WPSSO, which do write it, the module starts switched off. Either way it is a toggle like any other.

**It is light by design.**
No frontend JavaScript. No CSS. **No database tables**, now or later. One settings screen. WooCommerce is optional: without it you still get the full content graph.

### Features

Everything below is in the free plugin.

**Product schema**

* **`ProductGroup` for variable products**, with `hasVariant`, `variesBy` and `productGroupID`, and every variation as its own Product node.
* **Attribute mapping** to colour, size, material, pattern and audience, with multilingual detection and a per-attribute override.
* **Identifiers and detail**: SKU, GTIN from WooCommerce's own GTIN field, MPN from the meta the common feed plugins write, brand from the WooCommerce brand taxonomy, gallery images, item condition, weight and dimensions.
* **Ratings and reviews**: `AggregateRating` and real Review nodes from your WooCommerce reviews.
* **`Certification`** for EU energy labelling, written only when the data exists.

**Shipping and returns**

* **`shippingDetails` from your shipping zones**: destination, country and region, and the cheapest fixed rate. Local pickup is never counted as shipping.
* **`hasMerchantReturnPolicy`** from your declared return terms. Nothing appears until you fill them in.

**The site graph**

* **Organization**: identity, logo and social profiles.
* **WebSite**: with a SearchAction pointing at your site search.
* **WebPage**: subtyped correctly (CollectionPage on archives, ItemPage on products, CheckoutPage at checkout).
* **BreadcrumbList**: home, shop, category, product.
* **ItemList**: the products a shop or category page actually shows, with positions that continue across pages, including page-builder product widgets.
* **BlogPosting**: headline, author, dates, images and `speakable` hints.
* **FAQPage**: read automatically from core Details blocks. No shortcode, no proprietary block.

**AI search and social**

* **`/llms.txt`**: a cached, always-current markdown summary of your site.
* **Product Open Graph tags** (`product:price:amount`, `product:availability`) for Facebook catalogues and Pinterest rich pins.
* **Meta descriptions, Open Graph and Twitter cards** where no SEO plugin writes them.

**Compatibility**

* **Automatic back-off** beside full SEO plugins and structured-data plugins, with a duplicate-markup warning.
* **Opt-in theme switches**: turn off a theme's duplicate product microdata, breadcrumb markup, schema, meta description or Open Graph tags, through the theme's own hooks. Off until you turn them on.
* **Classic and block themes alike**: markup goes in the page head, so it works on block templates where WooCommerce prints no product markup at all.
* **WooCommerce High-Performance Order Storage and the Cart and Checkout blocks**: compatibility declared.
* **Variation swatches plugins**: NeoSEO reads WooCommerce's own variations, so swatches change nothing.

**Running it**

* **Dashboard**: how much of your catalogue carries schema, and what each module is doing.
* **Schema inspector**: the real JSON-LD graph for any page you choose.
* **Search Appearance box** on the product editor, with a live search-result preview.
* **Module toggles**: switch any part off.

**For developers**

Extend or override anything through filters:

`neoseo_schema_providers`, `neoseo_schema_graph`, `neoseo_product_list`, `neoseo_product_node`, `neoseo_product_group_node`, `neoseo_product_variants_node`, `neoseo_product_mpn`, `neoseo_product_condition`, `neoseo_product_certification`, `neoseo_attribute_property`, `neoseo_offer_shipping`, `neoseo_offer_return_policy`, `neoseo_meta_description`, `neoseo_description_post_types`, `neoseo_webpage_type`, `neoseo_llms_txt`, `neoseo_module_enabled`

### Documentation
For the full feature table, the theme compatibility list and how each Search Console warning is fixed, visit:
[NeoSEO on neoplugin.com](https://neoplugin.com/product/neoseo)

== External services ==

This plugin does not connect to any external service. Your structured data is built on your own server from your own store's data, and nothing is sent anywhere.

== Installation ==

1. Upload the plugin files to the `/wp-content/plugins/neoseo` directory, or install through the WordPress plugins screen.
2. Activate the plugin.
3. Go to **NeoSEO > Settings** and fill in your organization profile.
4. If you sell physical goods, fill in the **Returns** section. Google asks for it, and NeoSEO publishes nothing there until you do.
5. Check any product with Google's Rich Results Test.

== Frequently Asked Questions ==

= Does NeoSEO fix "Merchant listings structured data issues detected"? =

It fixes the issues that come from missing product data WooCommerce already has. The usual ones in that email are `Missing field "shippingDetails"` and `Missing field "hasMerchantReturnPolicy"`: NeoSEO writes the first from your shipping zones and the second once you fill in the Returns section. It also writes the variant, brand, GTIN, image and rating fields the report checks. A warning about data your store does not hold, such as a GTIN you never entered, stays until you add the data.

= How do I fix Missing field "shippingDetails" in WooCommerce? =

Set up your shipping zones in WooCommerce with a flat rate or free shipping, and NeoSEO writes `shippingDetails` from them, one entry per zone. A zone whose only cost is a formula, or whose free shipping needs a minimum order, is left out, because no single number describes it. Google treats this field as recommended rather than required, so the warning does not block your listing, but products with shipping costs shown are more useful to shoppers.

= How do I fix Missing field "hasMerchantReturnPolicy"? =

Fill in the Returns section under NeoSEO > Settings: whether you accept returns, the window in days, how items come back, who pays return postage, and the country the policy applies to. NeoSEO adds the policy to every product's offer. A return policy is a promise to your customers as well as a signal to Google, so NeoSEO will not invent one, and nothing appears until you declare it.

= What is the difference between merchant listings and product snippets? =

They are two Search Console reports. **Merchant listings** covers pages where a product can be bought, for the shopping results and the product knowledge panel, and checks offers, price, shipping and returns. **Product snippets** covers the review stars and price shown on an ordinary search result. NeoSEO writes one Product node that feeds both.

= Do I need WooCommerce? =

No. The product features activate only when WooCommerce is present. The Organization, WebSite, WebPage, breadcrumb, article and FAQ graph works on any WordPress site.

= Will it conflict with my SEO plugin? =

No. NeoSEO detects Yoast, Rank Math, AIOSEO, SEOPress, Slim SEO, The SEO Framework, Squirrly and WPSSO, and disables its overlapping output automatically. Product variant markup is the one thing it keeps writing, because their free versions do not produce it, and that is a toggle like any other. Beside Yoast WooCommerce SEO or WPSSO, which do, it starts switched off.

= I already use a schema plugin. Will I get duplicate markup? =

NeoSEO detects the common structured-data plugins and switches its own schema module off. If it finds one it cannot switch off cleanly, it says so on the settings screen rather than quietly writing a second Product node.

= Is it compatible with my theme? =

Almost certainly. NeoSEO is checked against the most-installed WooCommerce themes on WordPress.org, and 233 are compatible: 195 out of the box and 38 with one setting. The full list is at [neoplugin.com/product/neoseo-theme-compatibility](https://neoplugin.com/product/neoseo-theme-compatibility).

If your theme is not on the list, it has not been tested yet, which is not the same as not working. NeoSEO writes its markup in the page head, so it does not depend on your theme's product templates.

= My theme prints its own schema. What do I do? =

Usually nothing: search engines pick one copy, so it is untidy rather than broken. If NeoSEO knows your theme, the Dashboard names what it duplicates and the Settings tab offers a switch to turn the theme's copy off (Kadence's product microdata, breadcrumb markup, Astra or Blocksy schema, a theme's own meta description or Open Graph tags, and others). The switch is off until you turn it on.

= Does NeoSEO add GTIN and MPN? =

Yes, when they exist. GTIN comes from WooCommerce's own GTIN, UPC, EAN or ISBN field, on the product and on each variation. WooCommerce has no MPN field, so NeoSEO reads the meta the common product feed plugins write, and the `neoseo_product_mpn` filter connects any other source.

= Will it slow my site down? =

No. NeoSEO adds no JavaScript and no CSS to your storefront and creates no database tables. The markup is a few kilobytes of text in the page head, and `/llms.txt` is cached until you publish or update something.

= My variations do not show colour or size =

NeoSEO recognises the usual attribute names in several languages. If yours is named something of your own, map it under Settings > Product attributes.

= How do I get FAQ schema? =

Build your FAQ with core Details blocks: question in the summary, answer inside. Two or more become a valid FAQPage node automatically.

== Screenshots ==

1. **The Dashboard** - how much of your catalogue carries schema, and what each module is doing.
2. **The schema inspector** - real ProductGroup output: productGroupID, hasVariant, and a variation with its own SKU, colour and offer.
3. **Settings** - return policy, attribute mapping and module toggles.
4. **The Search Appearance box** - on the product editor, with a live search-result preview.

== Changelog ==

= 1.0.0 =
* Initial release.
* Connected JSON-LD `@graph`: Organization, WebSite, WebPage, BreadcrumbList, BlogPosting, Product, FAQPage.
* WooCommerce `ProductGroup` with `hasVariant`, `variesBy` and `productGroupID`; every variation carries its own SKU, price, image and offer.
* Attribute mapping to colour, size, material, pattern and audience, with multilingual detection and a per-attribute override.
* `shippingDetails` derived from live shipping zones, and `hasMerchantReturnPolicy` from declared return terms.
* Brand from the WooCommerce brand taxonomy, product gallery images, item condition, MPN, weight and dimensions.
* `ItemList` on shop and category archives, with positions that continue across pages.
* Product Open Graph tags, meta descriptions and Twitter cards.
* `Certification` support for EU energy labelling, emitted only when the data exists.
* `/llms.txt` endpoint for AI crawlers.
* Automatic back-off for full SEO plugins and structured-data plugins, with a duplicate-markup warning. Variant markup stays on beside free SEO plugins and starts off beside Yoast WooCommerce SEO and WPSSO.
* Shop and category product list follows the products the page really renders: themes without WooCommerce support, and Elementor Pro or Divi product widgets with their own query.
* Opt-in theme compatibility switches: turn off a theme's duplicate product microdata, breadcrumb markup, schema, meta description or Open Graph tags, through the theme's own hooks.

== Upgrade Notice ==

= 1.0.0 =
First release: WooCommerce product schema with ProductGroup variants, shipping details from your zones, a return policy from your settings, and a connected JSON-LD graph.
