Skip to main content

Releases and Deploy Markers

When you tell StorePilot which build a page or a service is running, it marks the moment a new build appears — a dashed line on the traffic, errors and revenue charts — and an issue says what changed just before it began: «Deploy 2026.09.27-a1b2c (first seen), 30 minutes earlier».

What a marker means​

A marker StorePilot observes is the moment it first saw a release, not the moment it was deployed. It sees one the first time a page view, an error report or a service start names it. On a shop with visitors that is within seconds of the deploy; on a quiet staging site it can be later. The marker says «first seen» for that reason.

If your deploy pipeline announces the release instead — one curl at the end of the deploy, below — the marker is the deploy itself: the moment the pipeline gives, with the commit, the repository and a link to the run.

A browser release and a server release are marked separately, so a front-end deploy and a backend deploy on the same day are two lines.

Next.js and plain pages​

Set release on window.StorePilot before the loader tag, from a build-time variable:

<script>
window.StorePilot = { release: '%NEXT_PUBLIC_RELEASE%' };
</script>
<script async src="https://api.store-pilot.net/sp?k=YOUR_PUBLIC_KEY"></script>

In a Next.js app router layout:

<Script id="storepilot-release" strategy="beforeInteractive">
{`window.StorePilot = { release: ${JSON.stringify(process.env.NEXT_PUBLIC_RELEASE ?? '')} };`}
</Script>

The release rides on the first page view of every visit and on every error report. Leave it unset and nothing is marked — StorePilot never invents a version.

At most 20 different browser releases are marked per site per day. A page can name any release it likes, so a script that set a new value on every visit would otherwise draw a line per visitor; the ceiling keeps the chart readable, and releases past it are counted and skipped. A release reported by your own server is not limited this way.

NestJS and Node​

Pass release to the Node SDK:

StorePilotModule.forRoot({
key: process.env.STOREPILOT_KEY,
release: process.env.GIT_SHA,
});

The SDK announces itself when your service starts, and that announcement carries the release — the start of a process is when a new build goes live, so the marker appears right away instead of waiting for the next error. This needs @store-pilot/node 0.5.0 or newer.

Announce a deploy from your pipeline​

Add one step at the end of a successful deploy. It is authenticated with your site's secret API key — the same key source-map uploads use — because the caller is your build server, never a browser; there is no browser route for it. Keep the key in your CI secrets.

curl -fsS -X POST https://api.store-pilot.net/ingest/releases \
-H "X-StorePilot-Key: $STOREPILOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"version": "2026.10.13-a1b2c", "environment": "production",
"commit": "a1b2c3d4e5f6", "repo": "acme/shop",
"url": "https://github.com/acme/shop/actions/runs/123456789"}'

In GitHub Actions, after the deploy job's last step (jq is preinstalled on GitHub-hosted runners):

- name: Tell StorePilot about the deploy
if: success()
env:
STOREPILOT_API_KEY: ${{ secrets.STOREPILOT_API_KEY }}
RELEASE: ${{ github.sha }} # the same string your site reports as `release`
run: |
curl -fsS -X POST https://api.store-pilot.net/ingest/releases \
-H "X-StorePilot-Key: $STOREPILOT_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg version "$RELEASE" \
--arg commit "$GITHUB_SHA" \
--arg repo "$GITHUB_REPOSITORY" \
--arg url "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \
'{version: $version, environment: "production", commit: $commit, repo: $repo, url: $url}')"
FieldMeaning
versionRequired, 1–60 characters. The same string your pages, errors and Node SDK report as release — that is how an issue is matched to the deploy.
environmentOptional, up to 30 characters: production, staging, … prod and dev are read as production and development, exactly as on an error.
commitOptional. The commit sha, 7–40 hexadecimal characters.
repoOptional, up to 200 characters — acme/shop, or the repository's address.
urlOptional, https:// only, up to 500 characters — the run, a preview or the release page. A link carrying a username or password is refused; a token in its query string is removed before it is stored.
deployedAtOptional ISO 8601 time. Defaults to the moment StorePilot receives the call; more than 10 minutes in the future, or before the site was added to StorePilot, is refused.
componentsOptional, up to 10 name → version pairs, e.g. {"web": "1.4.2", "api": "1.4.1"}. A name over 40 characters or a version over 60 is shortened, not refused.

The first announcement of a version for an environment answers 201 {"ok": true, "id": 812, "created": true, …}. Announcing the same version for the same environment again — a re-run job, a second step adding the commit — answers 200 with the same id and created: false: nothing is duplicated, the details it states are added and the ones it leaves out are kept, and the marker does not move — the first announcement dates the deploy. The same version for another environment is a deploy of its own. A body StorePilot cannot accept is a 400 saying what is wrong; a missing or wrong key is a 401. The route takes 60 calls a minute per site, the same as source-map uploads.

Announcing a release says nothing about how your shop is installed, so it never changes which modules your site is offered and it does not complete the setup wizard — only data from your pages or your server does that.

On an issue​

An issue shows the change that came at most one day before it first appeared, and — if it had been resolved and came back — the change just before it came back, with how many minutes earlier. A change older than a day is not shown: it is not evidence about this fault, and stretching the window until something turns up would blame whatever happened to be last.

When the pipeline announced the deploy, two more things hold:

  • The announcement is named, not the sighting. A browser usually sees a new release a minute or two after the pipeline announced it; the issue still names the announced deploy, counting the minutes from the pipeline's moment rather than from the browser's.
  • A deploy announced for another environment is never named. A production issue is not blamed on a staging deploy made on the same site. Markers StorePilot only observed carry no environment and are considered for every issue, as before — and so is every marker when the issue itself reports no environment.

A connected AI client reads the same releases through the list_releases tool — each version with every marker for it and how many issues it introduced and how many came back in it — and narrows list_issues to what one release introduced. See Connect your own AI client.

WordPress​

On WordPress the plugin (1.36.0 and later) reports what changed on the site as markers of their own: a plugin updated, installed, removed, activated or deactivated, the theme updated or switched, and WordPress itself updated — each with the version it went to.

It works by comparing a list of names and versions, not by listening for one kind of update, so an update copied in over FTP or applied by your host is reported too. The comparison runs when somebody opens Plugins, Themes, Updates or the StorePilot screen in wp-admin, and when WordPress finishes an update itself — never on a page your shoppers load, and nothing is scheduled. Two consequences worth knowing:

  • The first run only remembers the list. Nothing is reported the day the plugin is installed or updated to 1.36.0; otherwise every plugin on the site would read as "installed".
  • A change is dated when it is noticed. An update made through wp-admin is noticed in the same request. One made over FTP is dated the next time one of those screens is opened.

A release set through the storepilot_release filter is marked the same way as above. The plugin's PHP error reports carry it as well, and because a PHP report is the server's word, the first one under a new release also marks it as a server release — so one deploy can show as a browser line and a server line.