Marketing
IndexNow for GoCommerce
A Go package that tells search engines a page changed, the moment it does. When a product or collection changes, its storefront URL is batched for 30 seconds and submitted to IndexNow, which Bing, Yandex, Seznam and Naver read. Google does not take part.
- Marketing module
- 7 settings
- 9 tests
- ext/indexnow
What it does
In the package’s own words: “IndexNow is a ping and nothing more. One POST carrying the URLs that changed, and Bing, Yandex, Seznam and Naver fetch them rather than waiting to crawl. There is no account, no console and no verification round trip: a key file on the site is the verification.”
The module listens for products created, updated and deleted, and collections updated. It builds each page’s storefront URL from the storefront address and a path pattern, and when a product’s slug changes it submits the old address too — so a search engine looks at the 404 and drops it, rather than keeping a dead URL until it happens to recrawl.
The key file has to answer at the root of the storefront, because IndexNow trusts a key only for URLs in its own folder and below — and in a headless store the storefront is not this server. So the engine keeps the key and the storefront serves it: as a static file, or by proxying GET /x/indexnow/key.
Configuration
One setting is required, the storefront URL, and it lives on the Plugins screen only; Config holds nothing but test and proxy overrides. The plugin starts switched off — enable it there.
| Setting | Environment variable | Required | What it does |
|---|---|---|---|
storefront_urlStorefront URL | — | Yes | Where the pages actually are, and so the host the key file must answer on. Panel only. |
keyKey | — | No | Left empty, one is generated on first use — 32 hex characters. Anything from 8 to 128 letters, digits and dashes. |
product_pathProduct page path | — | No | The product page’s path, /products/{slug} by default. |
collection_pathCollection page path | — | No | The collection page’s path, /collections/{slug} by default. |
Window | — | No | How long URLs collect before one submission goes: 30 seconds by default. Go only. |
Endpoint | — | No | Overrides https://api.indexnow.org/indexnow, for tests. Go only. |
HTTP | — | No | Replaces the HTTP client, which otherwise times out after 15 seconds — for tests, or a store behind a proxy. Go only. |
The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own main() you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.
Setting it up
- Install the modulePass indexnow.New() to gocommerce.New in your own main(), as below. The reference binary has no flag for it; examples/store/main.go installs it.
- Switch it onEnable IndexNow on the Plugins screen and set the storefront URL — and the product and collection paths, if yours differ.
- Serve the keyPOST /api/admin/x/indexnow/key mints a key and says what to serve: <key>.txt at the storefront’s root, holding the key with no trailing newline — or a route proxying /x/indexnow/key.
- Check itGET /api/admin/x/indexnow/check fetches the file from the storefront, compares it byte for byte, and names the problem — a 404, a wrong key, a stray newline — before anything is submitted.
main.go
import (
"github.com/itswadesh/gocommerce/core"
"github.com/itswadesh/gocommerce/ext/indexnow"
)
// Nothing to configure here: the storefront URL is a plugin
// setting, and the storefront serves the key file.
app, err := gocommerce.New(cfg, indexnow.New()) The package doc’s own example, with its imports. cfg is your gocommerce.Config; indexnow.New also accepts an optional indexnow.Config. Import path github.com/itswadesh/gocommerce/ext/indexnow.
How it works
-
Batched on purpose
An operator repricing a range edits thirty products in two minutes. URLs collect for 30 seconds and go as one submission, and a product saved four times is submitted once.
-
One endpoint for all
Submissions go to api.indexnow.org, which forwards to every participating engine, rather than to each engine separately — the practice the shared endpoint exists to stop.
-
Only this host’s URLs
IndexNow refuses a batch that mixes hosts, so a URL not on the storefront’s host is dropped before sending rather than losing the rest. At most 10,000 URLs go in one request.
-
A byte-for-byte check
The check compares the storefront’s file with the key exactly, because a trailing newline looks right in a browser and is refused by IndexNow — the commonest way, the package says, this setup goes wrong.
-
Submit, exported
The module’s Submit method is exported, so a host can send pages the module does not know about — a CMS page, a hand-built landing page — without reimplementing the protocol.
-
No tables
The key lives in the plugin’s settings and nothing about submissions is stored. What was submitted and when is, in the package’s words, a question the search engine answers.
What it does not do
Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.
- No GoogleGoogle does not take part in IndexNow. A store that wants Google to know sooner still needs Search Console and a sitemap.
- Products and collections onlyContent pages, the home page and category pages are not submitted, unless your own code calls Submit for them.
- Fire and forgetA failed submission is logged and dropped, not retried. URLs waiting in the 30-second window are held in memory, so a restart inside it loses them.
- The key file is yours to serveThe engine cannot put the key on the storefront’s host. Until the storefront answers with it, IndexNow refuses the submissions.
- Off until switched onInstalling the module does not enable it, and with no storefront URL set it submits nothing.
- The panel’s hint is wrongThe Storefront URL field’s help says the key file is served from the engine. It is not: as the package doc explains, the storefront serves it.
FAQ
Questions about the IndexNow module
Does this tell Google?
No. Google does not take part in IndexNow, and the module says so rather than pretending otherwise. For Google, Search Console and a sitemap are still the route — the sitemaps module serves one.
Where does the key file go?
At the root of the storefront’s host: https://shop.example/<key>.txt, holding the key and nothing else — no trailing newline. The engine cannot serve it there in a headless store, so the storefront does, as a static file or by proxying GET /x/indexnow/key.
What gets submitted?
A product’s page when it is created, updated or deleted — and its old address too, when its slug changed — and a collection’s page when it is updated. Everything that changed in a 30-second window goes in one submission.
Does it need an account with the search engines?
No. IndexNow has no account and no console: the key file on the storefront is the whole of the verification.
Source
Everything on this page is read from ext/indexnow in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.Bing, Yandex, Seznam and Naver are trademarks of their owners; this module submits URLs to the shared IndexNow endpoint and implies no endorsement by any of them. See trademarks.
Try it against a store of your own
The one-command stack gives you GoCommerce’s API and admin on your own machine in minutes. Add this module to it and try it on test orders before a real one depends on it.