Early accessCodeGecko is opening to a first group of teams.Join the waitlist

How it works

From deploy to verdict, in five steps.

Your CI tells CodeGecko which commit is live. Your visitors’ browsers report how it performed. CodeGecko compares every release with the one before, page by page and device by device, and tells you what got slower and why.

  1. Today

    Set up

    Project, CI step, script tag.

  2. Next deploy

    First release

    Release one starts collecting.

  3. Deploy after that

    Compare

    Release two vs release one.

  4. ~30 visits per page

    First verdict

    Hours on busy pages.

01Connect

Create a project. Get two keys.

Name the project and enter your site’s origin. You get two credentials with separate jobs, so the one that lives in browser code can’t do anything dangerous.

  • Both are shown once. Only their SHA-256 hashes are stored.
  • Rotate the public key any time; the old one keeps working for 24 hours.
  • The public key works only from the origin you registered.
Server only · CI

Deployment secret

Lives in your CI secrets

8f2a••••••••••••••••

  • Register releases
  • Send visit data
  • Read reports
  • Rotate or delete keys
Browser · your origin

Public key

Lives in your script tag

cg_pub_8f2a••••••••

  • Send visit data
  • Register releases
  • Read reports
  • Rotate or delete keys

Reading reports and managing keys happens in the dashboard, signed in. Neither key can do it.

02Deploy

Tell CodeGecko what shipped.

After each production deploy, one CI step sends the live commit and its recent history. Each new commit becomes the next release: v1.0.0, v1.0.1 and so on.

  • Works from any CI that can run curl
  • Rolling back to an earlier commit keeps its release number
  • Retries of the same commit are safe
  • Each release keeps the commits that are new since the last one

Register before you collect

Measurements that arrive before your first release is registered are rejected, and the script stops sending for that visit. Run the CI step once before you add the script tag, or use data-commit.

No access to CI?

Add data-commit to the script tag with the build’s commit. Unknown commits then register themselves on first visit, up to 20 a day.

After each production deployBearer: deployment secret
# .github/workflows/deploy.yml
- name: Tell CodeGecko what shipped
  if: github.ref == 'refs/heads/main'
  env:
    CODEGECKO_SECRET: ${{ secrets.CODEGECKO_SECRET }}
  run: |
    git log -n 100 --format='%H%x09%P%x09%an%x09%s' |
    curl -X POST https://codegecko.dev/api/releases \
      -H "Authorization: Bearer $CODEGECKO_SECRET" \
      -F projectId=$CODEGECKO_PROJECT -F commit=$GITHUB_SHA \
      -F 'commits=<-'
Response201 Created
{
  "version": "v1.0.7"
}
03Collect

Real visits, quietly measured.

Add one script tag to every page. Built on Google’s web-vitals library, it records how each page load felt and what it cost, then sends a small batch when the visitor leaves.

One measurement, as sentPOST /api/v1/collect
{
  "metric": "LCP", "value": 2710,
  "path": "/products/:slug",
  "device": "mobile"
}

On every page, in <head>

What each part does

<script async
src="https://codegecko.dev/collector.js"
RequiredThe collector. ≈7 kB, loads async, never blocks rendering.
data-project="your-project-id"
RequiredWhich project the visits belong to.
data-key="cg_pub_…"
RequiredYour public key. Works only from the origin you registered.
data-routes="/blog/:post, /docs/:page"
OptionalYour own page groups. Otherwise /products/blue-shoe-42 becomes /products/:slug.
data-sample="0.25"
OptionalMeasure a share of page loads on busy sites.
data-commit="a3f9c1e"
OptionalOnly if you can’t add the CI step.
></script>

Mobile or desktop

From the browser’s own hint, or under 768 px wide.

Sent in the background

Batched when the page is hidden. Never retried; it stops for the visit after any rejection.

Nothing personal

No query strings, fragments or cookies. IDs, emails and tokens in URLs and error messages are replaced before anything leaves the browser.

04Compare

Every metric gets a verdict.

For each page, device and metric, CodeGecko takes the 75th percentile of this release and the one before, then asks the same three questions. No AI guesses, no averages hiding a bad page.

  1. 1

    Enough data on both sides?

    At least 30 visits for this page, device and metric in both releases. Once a newer release replaces the short one, no more can come.

    Not yetGathering data
    Replaced shortinconclusive
  2. 2

    Is the change bigger than noise?

    The typical visit has to move by more than 5% of the old value, or the metric’s floor, whichever is larger.

    Nounchanged
  3. 3

    Which way did it move?

    Every metric is “lower is better”, so the direction decides the verdict.

    Lowerimproved
    Higherregressed

Worked example · LCP, /, mobile

visits 214 / 196 both over 30
typical 2.58s → 2.71s +130ms
threshold max(5% × 2.58s, 100ms) = 129ms
130ms > 129ms, and higher regressed

Health badges (Good, Needs improvement, Poor) use Google’s Core Web Vitals ranges and show where a metric stands. The verdict shows how it moved.

05Report

One verdict per release, and the why.

Metric verdicts roll up into one word for the release on each page, starting with /. When something got slower, the report puts the evidence next to it.

Metric verdicts

Release

  • improvedregressedunchangedmixedSome improved and some regressed.
  • regressedunchangedunchangedregressedAt least one regressed, none improved.
  • improvedunchangedunchangedimprovedAt least one improved, none regressed.
  • unchangedunchangedunchangedunchangedNothing moved past its threshold.
  • Gathering dataGathering dataGathering dataGathering dataNot enough data yet to say.
  • inconclusiveinconclusiveinconclusiveinconclusiveThe release before was replaced before it got enough visits.

Then the why.

Next to anything that got slower, the report shows the evidence.

  • Load steps

    DNS, connect, server, download and DOM ready, so a slower page shows where the time went.

  • Page weight

    JS, CSS, image and font bytes per page, with the growth marked.

  • Third-party cost

    Bytes and main-thread blocking from other domains, new ones flagged.

  • Long animation frames

    Time the page froze, and the script behind most of it.

  • JavaScript errors

    Share of visits with an error, and messages new in this release.

  • Commits that shipped

    Listed with a GitHub compare link. Which one caused it is still your call.

When you’ll see results

Your second release is your first verdict.

What your dashboard shows, from setup to the first verdict.

  1. Today

    Waiting for your first release

    • Project created
    • CI step added
    • Script tag on the site
    • First release registered

    Create the project, add the CI step and the script tag.

  2. Next deploy

    v1.0.0 · collecting

    First release
    /182 visits
    /products/:slug140 visits
    /cart46 visits

    Your first release starts collecting. Nothing to compare yet.

  3. Deploy after that

    v1.0.1 vs v1.0.0

    Comparing as visits arrive
    /30 / 30
    /products/:slug22 / 30
    /cart6 / 30

    Release two is compared with release one as visits arrive.

  4. ~30 visits per page

    v1.0.1 vs v1.0.0

    Release verdictimproved
    LCPimproved
    INPunchanged
    CLSunchanged

    Busy pages get a verdict within hours; quiet ones keep gathering data, and end inconclusive if the next release comes first.

What’s measured

What visitors feel, and what it costs.

LCP, INP and CLS are Google’s Core Web Vitals. The rest explain them, and some only count when the browser can measure them.

Metric

Measures

In plain words

Unit

Google “good”

Role

LCPLoadingWhen the largest element finishes rendering.ms≤ 2.5sDecides the verdictms · good ≤ 2.5s
INPResponsivenessHow fast the page reacts to taps, clicks and keys.ms≤ 200msDecides the verdictms · good ≤ 200ms
CLSVisual stabilityHow much content shifts unexpectedly.score≤ 0.1Decides the verdictscore · good ≤ 0.1
FCPFirst paintWhen the first text or image appears.ms≤ 1.8sDecides the verdictms · good ≤ 1.8s
TTFBServer responseTime until the first byte arrives.ms≤ 0.8sDecides the verdictms · good ≤ 0.8s
LoAFMain-thread blockingTime long frames froze the page. Chrome and Edge.ms—Decides it when measuredms
WeightPage weightCompressed JS, CSS, image and font bytes.kB—Decides it when measuredkB
ErrorsJavaScript errorsShare of visits with an uncaught error.%—Decides it when measured%
LoadLoad breakdownDNS, connect, server, download, DOM ready.ms—Explains, never decidesms
3rd partyThird-party costBytes and blocking from other domains.kB · ms—Explains, never decideskB · ms

“Good” is Google’s 75th-percentile range and drives the health badge. The verdict compares releases, whatever the range.

Built carefully

Private and safe by default.

What CodeGecko keeps, how it keeps it, and the straight answers on what it can’t do yet.

What it does

  • No personal data

    Pages are templates. No query strings, fragments, cookies or identifiers.

  • Keys stored as hashes

    Shown once, never kept in plain text.

  • Your data is yours

    Row-level security isolates every project. Delete one and everything goes with it.

  • Rate-limited collection

    Per-project limits per minute and per month, enforced in the database.

What it doesn’t do yet

  • Name the commit that caused a regression

    Code-diff analysis is on the roadmap.

    On the roadmap
  • Measure route changes inside single-page apps

    Every full page load is measured.

  • Run synthetic lab tests

    Everything comes from real visits.

Your next deploy is your first data point.

Set it up once. Every release after that is compared automatically.

codegecko · setup

# about 10 minutes, once

project created · shop.example

CI step added

script tag on every page

# then, on every deploy

POST /api/releasesv1.0.0

collecting… your first data point