Custom audit vs. plugin
| Custom audit + config | Plugin | |
|---|---|---|
| Distribute on npm | Manual — ship the config file | ✅ Built-in |
| Stable public API | ❌ May change between minor versions | ✅ Semver-stable |
| Custom gatherers | ✅ | ❌ |
| Modify core categories | ✅ | ❌ |
Change config.settings | ✅ | ❌ |
New audit principles
A good Lighthouse audit should satisfy all of the following criteria before it is written.- Applicable at scale — affects a significant portion of web developers based on severity and reach.
- Improves mobile web — contributes meaningfully to better end-user experience.
- Low overhead — does not significantly impact Lighthouse runtime performance or bundle size.
- Non-duplicate — measures something not already covered by existing audits.
- Measurable — has a numeric score (performance) or clear pass/fail state.
- Actionable — when failing, gives specific advice. If failure can be tied to a resource (DOM element, script, line of code), uses the appropriate detail type.
- No third-party APIs — completes the audit check without external API calls.
Actionability requirements
- Specific advice must be given when an audit fails. If an audit can fail in multiple ways, each path needs its own guidance.
- If the failure applies to a specific resource, use the appropriate detail type (see table below).
- If multiple failures can occur on a single page, return a table — do not collapse everything into a binary score.
Detail types
| Detail type | Resource | Notes |
|---|---|---|
node | DOM element | Set path to a devtoolsNodePath |
source-location | Code / network resource | Points to a specific line and column |
code | Freeform | Rendered as monospace like this |
url | Network resource | Rendered as a pretty link |
thumbnail | Image resource | Same as url, but shows a thumbnail |
link | — | Arbitrary label / URL combination |
bytes | — | Value in bytes, formatted as KiB in the report |
text / ms / numeric | — | Plain values; ms and numeric accept a granularity field |
Granularity
Thebytes, ms, and numeric types accept an optional granularity field. The value must be an integer power of 10 (e.g. 0.001, 0.1, 1, 10). The formatted value is rounded to that nearest number. Default is 0.1 (except ms, which defaults to 10).
Writing a custom audit
Write the audit class
An audit extends
Audit from lighthouse and implements meta and audit(). This example detects memory usage above a threshold using a custom MemoryProfile artifact.memory-audit.js
Write a gatherer (if needed)
If your audit needs data not available in the built-in artifacts, write a custom gatherer. Gatherers run during page load and produce a named artifact.
memory-gatherer.js
Wire everything into a config
Use
extends: 'lighthouse:default' to run your audits alongside the full default suite. All arrays are concatenated with the defaults; primitive values override them.custom-config.js
When extending the default config, arrays (like
audits and artifacts) are concatenated with the defaults. Primitive values like settings.throttlingMethod override the default.Audit meta properties
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Kebab-case identifier. Filename should match. |
title | string | Yes | User-visible title when the audit passes. |
failureTitle | string | No | User-visible title when the audit fails. |
description | string | Yes | Why the audit matters. Markdown links supported. |
requiredArtifacts | Array<string> | Yes | Artifacts that must be present for the audit to run. |
scoreDisplayMode | string | No | "numeric", "binary", "manual", or "informative". |
Audit ID naming policy
Audit IDs should be based on the noun of what the audit surfaces, not a verb describing the check.| Bad | Good | Reason |
|---|---|---|
no-vulnerable-dependencies | vulnerable-dependencies | No no- prefix |
redirects-http | http-redirect | No verbs |
uses-long-cache-ttl | cache-headers | No verbs |
is-crawlable | crawlability | No verbs |
images | oversized-images | Too broad |
used-css | unused-css | Prefer failing-state adjective |
Audit title conventions
- Opportunity audits: Use an imperative
titledescribing the fix. Example: “Compress large images”. - Standard audits: Use a descriptive
titleandfailureTitlethat state what the page is or is not doing. Example:title: "Page works offline",failureTitle: "Page does not work offline".
Returning structured details
When your audit fails for a specific resource, return adetails object so the report can render a table or list.
Scoring guidance
- Return a number between
0and1. Scores above0.9are collapsed into “Passed audits” by default. - Weight audits within a category by their relative importance using the
weightfield inauditRefs. - When an audit’s advice does not apply to the current page, return
{score: null, notApplicable: true}rather than inflating the score with a pass.