Product
The audit
A full analysis of your site, page by page, in a real browser
Contents
Run an audit
The simplest way is the free trial at the top of the home page, which measures a page without installing anything or creating an account and returns the full report, with its score and everything that needs fixing. The same measurement can also be run through the API, three times a day per domain, and it is in fact exactly the same engine that then runs in your CI, where it has no limit at all since it runs on your side.
curl -s https://api.getgrammage.com/v1/tests \
-H 'content-type: application/json' \
-d '{"url": "https://example.com/"}'include:
- project: solyzon/products/grammage/grammage
ref: prod
file: ci/grammage.gitlab-ci.yml
grammage:
extends: .grammage
needs: [preview]
variables:
GRAMMAGE_CATEGORY: autogrammage audit https://example.com/ --mode fast --format html,agent
grammage audit --site https://example.com/ --category auto --parallel 4A real visit, in five steps
Grammage does not read the code of the page to guess what it weighs, it really visits it, and always in the same way, following a fixed protocol called grammage-1.
Loading
Chromium opens the page without a window, as your visitor’s browser would, and waits for it to declare itself loaded, one minute at most.
Waiting for calm
A modern page often keeps working after it has loaded, while its JavaScript takes over, so Grammage waits for one second with no network exchange and almost no computation, fifteen seconds at most, because some pages never settle.
Scrolling to the bottom
The page scrolls screen after screen, with the same gesture as a mouse wheel, to trigger deferred images and everything that waits for you to get close. Grammage never answers the cookie banner, neither to accept nor to refuse, so the measured page looks more like the one a visitor who refuses sees, and the report says so.
Three seconds of observation
Everything that still happens is counted, a carousel that turns or an advert that reloads for example, when the page should no longer be doing anything.
The return visit
Grammage comes back to the page with the cache already filled, to see what it makes someone download again when they come back to see it.
Each page is measured three times, and the report keeps the middle value of each quantity, so that one pass that happens to be slow or heavy does not distort the result. The simulated phone has a 412 × 823 pixel screen and a processor slowed down four times, to look like a mid-range model, and the computer has a 1,920 × 1,080 pixel screen. In our September 2026 tests, the weight, the requests and the number of elements are reproduced to within 1% from one measurement to the next, except when the page itself changes from one load to the next.
What is recorded
During these passes, Grammage records everything that weighs on the footprint of the page. Part of it goes into the score, and the rest is still shown in the report, either because it varies too much from one measurement to the next to be scored honestly, or because it is more about speed than about footprint, but it really helps to understand where the energy goes.
What goes into the score
| Quantity | What it tells |
|---|---|
| Transferred weight | the bytes that really travelled over the network, compression included |
| Requests | their number, a redirect counting as one request more |
| DOM elements | counted like EcoIndex, without the inside of SVG drawings |
| Good practices | fifteen checks, detailed just below |
| Hosting | green according to the Green Web Foundation, and the country of the server |
What is shown without being scored
| Quantity | What it tells |
|---|---|
| Whole page | the weight once the page has been scrolled to the bottom, which is used for carbon |
| Computing time | the processor time of the whole visit |
| Idle activity | the processor and the bytes that a scrolled page still consumes |
| Unused code | the JavaScript that never runs and the CSS that is never used, file by file |
| WebSocket frames | what a chat widget or a live feed exchanges |
| TTFB, FCP, LCP, CLS | the speed of the first byte and the first paint, and the stability |
| Return visit | what the page downloads again with the cache already filled |
| Carbon | the grams of CO₂ eq. per visit, according to Sustainable Web Design v4 |
The score out of 100
The score adds up five parts, weight, requests, the number of DOM elements, good practices and hosting, and compares the page with those of its category. The weight of each part, the curves and the benchmarks are detailed on the method page.
The fifteen good practices
The rules come from the 115 web eco-design good practices of the Green IT collective (the RWEB references), from the general eco-design framework of Arcep and Arcom (the RGESN) and from the W3C Web Sustainability Guidelines (WSG). Each is worth 1, 2 or 3 depending on what it really weighs on the footprint, a rule that is half followed earns half of its weight, and a rule that does not apply to the page, a rule about videos for a page without video for example, simply leaves the calculation.
| Rule | Weight | Passed when | References |
|---|---|---|---|
text-compression | 3 | at least 95% of text bytes over 1 KB arrive compressed in Brotli, gzip or zstd, and half credit between 90 and 95% | RGESN 6.3, RWEB_0076, WSG 5.3 |
static-cache | 2 | every image, font, stylesheet, script or media file has a cache duration, half credit when the browser can only guess it | RGESN 6.2, RWEB_0075, WSG 5.2 |
http2 | 1 | no resource still goes through HTTP/1 | RWEB_0083, WSG 5.12 |
redirects | 2 | one redirect at most | RWEB_0112, WSG 5.4 |
http-errors | 2 | no request answers with an error, a 404 or a 500 for example | WSG 5.4 |
domains | 1 | five domains at most | RGESN 6.7, RWEB_0082, WSG 3.5 |
no-polling | 2 | no address is requested twice during the three seconds of observation | WSG 5.11 |
image-formats | 3 | more than three raster images out of four are in WebP or AVIF | RGESN 5.1, WSG 4.9 |
image-resized | 2 | no image is more than twice as wide as its display, screen density included | RGESN 6.4, WSG 4.9 |
image-lazy | 2 | every image outside the first screen has loading="lazy" | RGESN 6.5, RWEB_0051, WSG 4.9 |
font-families | 2 | two font families at most | RGESN 4.8, RWEB_0032, WSG 4.12 |
font-woff2 | 1 | every font is served as WOFF2 | WSG 4.12 |
no-autoplay | 3 | no video or sound starts by itself | RGESN 4.1, RWEB_0106, WSG 4.9 |
no-infinite-animation | 1 | no endless animation is still running at the end of the measurement | RGESN 4.1, RWEB_0009, WSG 4.10 |
meta-description | 1 | the page has a description, which avoids repeated searches | RWEB_0011, WSG 3.8 |
Each rule that is not followed comes with its fix and with the gain you can expect on every view, in bytes and then in carbon, calculated on the real weight of the offending files, so that you start with what really weighs.
Fixes written for your framework
The score never depends on the framework, since Grammage measures the page as the browser receives it. What changes with the framework is the way to fix, and advice that only says to “serve images as WebP” does not gain much for someone working on Nuxt, whereas <NuxtImg format="webp"> saves them time right away. Grammage therefore recognises the framework of each page during the measurement, through the markers it leaves in the page, the addresses of its files, its cookies and its generator tag, and it accompanies each generic fix with the one that is specific to it.
- Nuxt
- Next.js
- Astro
- WordPress
- SvelteKit
- Laravel
- Shopify
- React
- Vue
- Gatsby
- PrestaShop
- Django
- Symfony
- Drupal
- Joomla
- PHP
- Remix
- Angular
- Webflow
- Wix
- Hugo
<picture>
<source srcset="/hero.avif" type="image/avif" />
<img src="/hero.webp" alt="" width="1200" height="630" loading="lazy" />
</picture><template>
<NuxtImg src="/hero.jpg" format="webp" sizes="100vw md:50vw" loading="lazy" />
</template>import Image from 'next/image';
export function Hero() {
return <Image src="/hero.jpg" alt="" width={1200} height={630} sizes="100vw" />;
}---
import { Image } from 'astro:assets';
import hero from '../assets/hero.jpg';
---
<Image src={hero} alt="" format="webp" />| Framework or CMS | Specific fixes |
|---|---|
| Nuxt | images, compression, cache, fonts, domains, description |
| Next.js | images, compression, cache, fonts, domains, description |
| Astro | images, compression, cache, fonts, domains, description |
| WordPress | images, compression, cache, domains, description, lazy loading |
| SvelteKit | images, compression |
| Laravel | images, compression, cache |
| Shopify | images, cache |
| React | images, repeated requests |
| Vue | images, repeated requests |
| Gatsby | images |
| PrestaShop | images |
| Django | compression and cache with WhiteNoise |
| Symfony | generic fixes and those of PHP |
| Drupal | generic fixes and those of PHP |
| Joomla | generic fixes and those of PHP |
| PHP | compression and cache, on the server |
| Remix | generic fixes |
| Angular | generic fixes |
| Webflow | generic fixes |
| Wix | generic fixes |
| Hugo | generic fixes |
A Symfony without its bundles/ or a Django that sets no cookie often leave no trace in the page, and Grammage then gives the generic fixes, which remain right for everyone. It never guesses a framework it has not really recognised.
The whole site
For a whole site, Grammage reads its sitemap or follows its links, groups the pages by template and measures each one as a separate page, then draws a result for the site. The rules behind this choice and this weighting are on the method page.
Sites protected against robots
A page protected by an anti-robot service is declared not measured rather than scored, and Grammage never passes itself off as a human visitor. What to allow on your service is explained on the method page.
The report
The same report comes out in several formats, chosen with --format, and it is the same everywhere, whether the measurement comes from the site, from the API or from your CI.
| Format | File | What it contains |
|---|---|---|
html | grammage.html | the report to read, page by page, with the fixes and their gain |
pdf | grammage.pdf | the same report in A4, with its pagination, to pass it on |
json | grammage.json | the full report, whose shape does not change as long as schemaVersion is 1 |
agent | grammage-agent.md | the fixing brief to hand as it is to a coding agent or to a colleague |
rgesn | grammage-rgesn.md | the eight criteria of RGESN 2024 that the measurement touches, in Markdown and in HTML |
gitlab | CI reports | the Tests tab, the Code Quality widget and the Metrics widget of the merge request |
Handing the work to a coding agent
The grammage-agent.md brief says which site and which framework you are working on, then lists the fixes in the order in which they pay off the most, with the files to touch, the fix for the framework, the expected gain and the command that checks that the rule passes. It only contains what the measurement established, and never advice it does not back up.
Preparing an eco-design declaration
The RGESN helper takes, for each of the eight criteria of the framework that the measurement touches, the question asked, the Grammage rules that relate to it, what they give on your pages and the files recorded. It is not the declaration itself, which covers seventy-eight criteria, but rather the measured evidence to attach to it.
See what your site really weighs
Grammage brings together in a single tool the audit in a real browser, the code analysis in the CI/CD and a signed result that anyone can verify.
Free trial, no commitment.
Try it for free