Checking it worked
Geoffy does not take your word for it. After you publish, we fetch your live product page and look for our markup in the server-rendered HTML. A product stays pending until we find it, and your dashboard count only ever shows products confirmed on your real site.
If a product stays pending
| Reason | What it means | What to fix |
|---|---|---|
code_not_added | We fetched the page and our markup was not in it | The component is not on the page, or it is rendering on the client |
stale_version | Our markup is there, but it is an older copy | Nothing. Your cache clears itself within the revalidate window — one hour by default |
canonical_broken | The page does not name itself as canonical | See "Before you start" — most often a missing per-page metadata export |
You can check the same thing yourself:
curl -s https://yourdomain.com/en/products/your-handle | grep -c 'data-geoffy'A number greater than zero means it is in the server-rendered HTML, which is what matters. The same command works against your dev server while you are building — swap the host.
And the namespace
Geoffy checks the /apps/geoffy mount the same way — by fetching it, not by
trusting the setting. Check it yourself with:
curl -si https://yourdomain.com/apps/geoffy/sitemap.xml | head -20 A 200 is not the check. That is the one thing worth knowing
here, because it is what makes a broken mount look fine: a catch-all route in your app
answers every path — including this one — with your home page and a perfectly
healthy 200.
So Geoffy checks three things instead, and you can check the same three by eye:
| Check | Why |
|---|---|
| The response is genuinely proxied from Geoffy | Not your home page, not a CDN interstitial. If what comes back looks like your own site, a catch-all route is winning and the namespace route is not being reached |
| It is your site's content |
A GEOFFY_SITE_KEY copied from another project would otherwise confirm
a mount that is serving someone else's catalogue under your domain
|
content-type is application/xml or text/xml | A sitemap served as HTML is one a crawler will not parse |
If the mount is not confirmed, the dashboard says which of these it is:
| Reason | What it means |
|---|---|
not_mounted | The path answered, but not with our bytes — usually a catch-all route serving your home page, or the route file is not deployed yet |
wrong_site |
Our marker came back carrying a different site key. Your
GEOFFY_SITE_KEY belongs to another Geoffy site
|
unreachable | We could not fetch it at all. This is not the same as "not mounted" and is not recorded as a failure — we try again |
While the mount is unconfirmed, your llms.txt simply says less: it omits
the product twins and the Geoffy sitemap rather than pointing a crawler at URLs that
answer with your home page.
What a local run cannot do
Geoffy confirms your integration by fetching your live product page at
its canonical URL — the public one, not your machine. So until the integration is
deployed, products stay pending with code_not_added no matter how correct
everything looks locally.
That is the check working as intended: it reports what your visitors and the crawlers
actually get. Prove it locally with the curl above, ship, and let the
confirmation follow.
Astro specifics
Section titled “Astro specifics”code_not_added on a page you are sure is correct is almost always one of two things:
getGeoffyProductMarkupreturnednulland your guards rendered nothing. That is the helper working as designed — it returnsnullwhen Geoffy has nothing published for the handle, when Geoffy is unreachable, and whencanonicalUrldoes not match the page Geoffy published against. There is nodata-geoffy-skippedmarker on this side to tell those apart, so check the handle first.- The page was prerendered before you published. On a static build the markup is baked in at build time. Publishing afterwards changes nothing until you rebuild — see how updates arrive.
If the namespace check reports not_mounted on a site you believe is server-rendered,
confirm export const prerender = false is actually in the route file. A prerendered
[...path].ts fails the build outright, but a route that was never deployed simply
answers 404.