Skip to content

Shopify behind your storefront

The common shape: you render your own storefront in Astro and query Shopify’s Storefront API for the catalogue. Geoffy sits alongside, reading the products Shopify already synced to it.

What makes this easy: the handle Shopify gives you is the handle Geoffy wants. You already have it in scope, so there is nothing to map and nothing to store.

src/pages/products/[handle].astro
---
import Layout from "@/layouts/Layout.astro";
import { getGeoffyProductMarkup } from "@geoffy/headless/astro";
import { getProductByHandle } from "@/lib/shopify";
export const prerender = false;
const { handle } = Astro.params;
const product = await getProductByHandle(handle);
if (!product) return Astro.redirect("/404");
// One canonical, built once, used by the <link> and by Geoffy.
const canonical = `https://yourdomain.com/products/${handle}`;
const geoffy = await getGeoffyProductMarkup(
{ siteKey: import.meta.env.GEOFFY_SITE_KEY },
handle,
{ canonicalUrl: canonical },
);
---
<Layout title={product.title} description={product.description}>
<link rel="canonical" href={canonical} slot="head" />
{geoffy && <Fragment set:html={geoffy.jsonLdScript} slot="head" />}
<article>
<ProductGallery images={product.images} />
<h1>{product.title}</h1>
<BuyBox variantId={product.variants[0].id} price={product.priceRange} />
<Fragment set:html={product.descriptionHtml} />
{geoffy && <div data-geoffy-widget set:html={geoffy.widgetHtml} />}
</article>
</Layout>
  1. Shopify is the source of product facts. Title, price, availability, variants — your storefront reads them from the Storefront API, as it already does.

  2. Geoffy is a supplement, not a replacement. Its structured data deliberately carries no offers, no price and no availability: your page already has a product node with those, and two prices on one page with no rule for which wins is worse than one. Geoffy adds what the commerce node lacks — positive notes, audience, attributes, certifications.

  3. You do not sync anything. Shopify already pushed your catalogue to Geoffy when you connected the store.

The example sets prerender = false because a Shopify-backed catalogue changes — prices and stock most of all — and a prerendered product page freezes them until your next build.

If your catalogue is genuinely static, you can prerender the product page and still serve the namespace on demand: prerender is per route. But read how updates arrive first, because a fully static site has no accelerated path for Geoffy content either.

Everything else — the root files, the namespace, robots.txt, the IndexNow key — is identical whether Shopify is behind you or not. Follow the quickstart.