# SEO and structured data

> How search engines see a Smootify for Astro store. Covers the Seo component, the product structured data it writes, alt texts, canonical addresses and Google Shopping.

Status: Ready (Smootify 2.0)  
URL: https://www.smootify.io/docs/astro/start/seo  
Updated: 2026-10-21

A Smootify store is an Astro site, so search engines index real HTML: its pages, titles, URLs and structured data are in the page the server sends. Smootify writes the title, the description, the canonical address, the social tags and the product’s structured data from the store’s data, and adds the live data from Shopify in the browser. This page says what `<Seo>` writes, what you set yourself, and what stays with Shopify.

## Let the content give each page its text

Your product, collection and vendor pages are made from the content collections: see [Content from Shopify](https://www.smootify.io/docs/astro/start/content). The text of each entry is in the page before Smootify loads.

- **Write the visible text from the entry.** Render the product’s title from `name` and its description from `description`, even on elements that Smootify also fills. Smootify then writes the live values from Shopify over them. See [Build the product page](https://www.smootify.io/docs/astro/build/product-page).
- **Put `<Seo>` in the head of every page.** It writes the title tag and the meta description from the entry’s `seoTitle` and `seoDescription`. The title falls back to the name, and the description to a plain excerpt of the text. The canonical address is the page’s path on `site`, so set `site` in `astro.config.mjs` to the real address. See [Content from Shopify](https://www.smootify.io/docs/astro/start/content#5-seo-helpers).
- **Keep the URLs stable.** An entry’s slug is the cleaned Shopify handle. If you change a handle in Shopify, the page’s address changes: add a redirect from the old address.
- **Hide a product from the site in Shopify.** Like the Webflow sync, the loaders leave out a product whose metafield `seo.hidden` is `1` (or `sync.hidden`, or whose handle contains `untitled`), and a collection whose `sync.hidden` is `1`. The page is not built and the product is not in the sitemap. The metafield’s definition needs Storefront access: without it the product looks visible.

## The sitemap and robots.txt

The integration writes them at build time, from the pages it built: there is nothing to install or write by hand.

- **`sitemap.xml`** lists every built page at its canonical address, with its language versions and, for products, collections, pages and articles, the date of the last change. Pages with `noindex` and the 404 page are left out. It needs `site` in `astro.config.mjs`: without it the build skips the sitemap with a warning.
- **`robots.txt`** is written when the project has none, with a `Sitemap:` line. If your project has its own, in `public/`, it is left as it is: add the line `Sitemap: https://your-domain/sitemap.xml` to it. The build log says when the line is missing.
- **Pages rendered on demand** are not in the build. The integration adds the products, collections and vendors that the build loaders loaded; list any other on-demand address in the `extraUrls` of the `sitemap` option. `exclude` leaves addresses out, and `sitemap: false` turns it off.

```js
smootify({ siteId, sitemap: { exclude: ["/private/*"], extraUrls: ["/landing/"] } });
```

## Product structured data

On a product page, `<Seo type="product">` writes the product’s structured data (JSON-LD) into the HTML, so that Google can show the product as a rich result. It comes from the entry: there is no script to add.

It holds, from Shopify:

- the name, the description, the images and the brand (the vendor, or `brandFallback` when the product has none);
- for each variant: the SKU, the barcode when it is a valid GTIN, the price and currency, whether it is in stock, on backorder or sold out, and its link with `?variant=`;
- the options Google knows, when the product has options such as color, size, material or pattern;
- the rating, when the product has Shopify’s review metafields (see below).

A product with one variant is described as one product. A product with several variants and no options gets an offer with a price range. A product with options is described as a group, with one entry per variant.

**Which pages.** The ones with a `<Seo>`. A `product` page gets the product, a `collection` or `vendor` page a collection page with the list of its products, the `home` page the site and the organization, and an `article` a blog post. A page of type `other` (404, search, cart) gets the common tags only.

**The rating.** If a review app writes Shopify’s own review metafields, `reviews.rating` and `reviews.rating_count`, the product loaders read them and `<Seo type="product">` adds the rating to the structured data. It is added only with a rating and a count above zero: Google requires the count, so a rating without `reviews.rating_count` is left out. Both definitions need Storefront access. No list of reviews is written. Google recommends showing the rating on the page too. Stars and review widgets: see [Product reviews](https://www.smootify.io/docs/astro/features/reviews).

**One source.** `<Seo>` writes the structured data of the page. To add more objects, pass them in its `jsonLd` prop: they are written after the page’s own.

**Turn it off.** There is no prop that turns the structured data off. A page with `<Seo type="other">` writes none: use it for the pages that should not have any.

**Check it.** The structured data is in the page source. Test the page with Google’s Rich Results Test, or with the URL inspection in Search Console. Google decides whether a rich result shows.

## Google Shopping

For Google Shopping, the product feed of Shopify’s Google & YouTube app is the reference.

## Images and alt text

On the images it fills, Smootify writes the alt text of the image in Shopify. The entry holds it as `imageAlt`, empty when Shopify has none. Write alt texts in Shopify, on the product’s media.

The structured data also takes its images from the product’s media in Shopify. A product without media in Shopify has no image there.

If you group gallery images by alt text, the variant tag is part of the public alt text: see [Product gallery and media](https://www.smootify.io/docs/astro/build/product-gallery).

## The Shopify storefront

Shopify’s own storefront, the Online Store, can still show your products on the `.myshopify.com` address. If you do not use it, send its visitors to your site with Smootify’s Redirect theme: see [Send Shopify’s storefront visitors to your site](https://www.smootify.io/docs/astro/start/storefront-redirect).

## Where people get stuck

> [!STUCK]
> - **A product page has no structured data.** The page has no `<Seo type="product">` in its head, or its type is `other`.
> - **Canonical links point to `localhost`.** `site` in `astro.config.mjs` is still the placeholder. Set the real address.
> - **No rating in the structured data.** The product lacks `reviews.rating` or `reviews.rating_count`, the count is zero, or the definitions have no Storefront access.
> - **No image in the structured data.** The product has no media in Shopify.
> - **No GTIN.** The barcode in Shopify is not a valid GTIN, such as an internal code: it is left out.
> - **The product is missing from Google Shopping.** Shopping relies on the product feed of the Google & YouTube app.
> - **There is no sitemap.** `site` is not set in `astro.config.mjs`, or the option is `sitemap: false`. The build log says how many addresses it wrote.
> - **A hidden product still has a page.** The definition of `seo.hidden` has no Storefront access, so the loaders read nothing and the product looks visible.
