Microsoft has made clarity.js, the JavaScript file that powers its free Clarity behavioral analytics product, 1,257 bytes smaller in compressed form, a reduction of 4.5%, according to a post on the Clarity blog dated October 29, 2026. The work was carried out by an AI coding agent that ran more than 50 build-and-test experiments, keeping changes that shrank the file and reverting the rest. The largest single saving it found, 2,308 bytes, was never shipped: it would have broken Angular websites that rely on a library called Zone.js.
In Short
Microsoft made the little program that its Clarity analytics tool puts on websites about 4.5% smaller, using an AI helper that tried dozens of small code changes and kept only the ones that worked. That program loads on billions of web pages, so even a small trim means less code for every visitor's browser to download. An even bigger cut was possible, but Microsoft left it out because it would have quietly broken some websites built with Angular.
What clarity.js does
Every website that installs Clarity loads clarity.js. According to Microsoft, the script "captures the behavioral data behind Clarity insights" - the clicks, scrolls and page interactions that feed Clarity's heatmaps and session recordings. It sits in the same queue as everything else a page sends to a visitor's browser, from ad tags to fonts to consent banners.
"A lighter script means less JavaScript for the browser to download, which reduces Clarity's footprint on the billions of pages it runs on," the post states. It was written by Manu Nair and titled "How We Made clarity.js 4.5% Smaller Without Sacrificing Compatibility."
The audience for that file has widened over the past year. On November 11, 2025, Microsoft Advertising began requiring Clarity on third-party publisher placements, with clicks from pages lacking the script filtered out as non-billable. Eleven days earlier, on October 31, 2025, Clarity started enforcing consent signals for sessions from the European Economic Area, the United Kingdom and Switzerland. Clarity has also been pushed into more site builders and ad platforms, including a Google Ads integration that reached general availability on January 13, 2025 and a simplified WordPress plugin announced on July 30, 2025.
The post does not state the absolute size of clarity.js. PPC Land's own calculation, working back from the two figures Microsoft gives, puts the compressed script at roughly 27,900 bytes before the work and about 26,700 bytes after it. Because the 4.5% figure is rounded, the starting point could sit anywhere between about 27,600 and 28,200 bytes.
How the experiment loop worked
Microsoft's engineers did not hunt for the savings by hand. The work was handed to pi, an open-source coding agent published on GitHub under the MIT license, running a companion extension called pi-autoresearch. That extension describes itself as an autonomous loop that tries an idea, benchmarks it, keeps improvements and reverts regressions, and credits as its inspiration the autoresearch project open-sourced by AI researcher Andrej Karpathy.
According to Microsoft, each cycle followed the same five steps: make a change, build the script, measure the compressed output, run the test suite, then keep or revert the change based on the result. Each build-and-measure cycle took about 35 seconds. At that pace, the agent "can test 100 ideas in under an hour, with test-suite checks after every one," the post says.
Those economics are the core of the argument. Individual changes saved "maybe 5-50 bytes," and there was no way to know which ones would help until the gzipped output had been measured. "5-byte improvements aren't worth a human's time, but they're worth 35 seconds of automated experimentation," Nair writes. The agent also tried things the team "probably wouldn't have bothered with," including systematically testing 15 minifier options one at a time.
The post does not say how many of the more than 50 experiments were kept and how many were reverted, nor how the agent's accepted changes were reviewed before release.
Where the 1,257 bytes came from
Microsoft breaks most of the savings into five categories. All figures are gzip bytes.
| Change | Gzip saving |
|---|---|
| Namespace import elimination | 444 |
| Terser minifier options | 301 |
| Template literals replaced with concatenation | 110 |
| Large block deduplication | 109 |
| Removing entire functions | 84 |
Those five lines add up to 1,048 bytes, by PPC Land's calculation. That leaves 209 bytes, about 17% of the total, that the post does not attribute to a named category.
Namespace imports
The biggest win came from how the codebase imported its own modules. When JavaScript code imports a module as a namespace and then passes that namespace around as a value - placing it in an array, for instance - the Rollup bundler has to build a runtime object that wraps all of the module's exports. If the code only calls functions on the module directly, Rollup can inline those calls and skip the wrapper.
clarity.js had been doing the former. A single array listed five modules - diagnostic, layout, interaction, performance and dynamic - forcing Rollup to generate five namespace wrapper objects. Switching to named imports saved 444 bytes across three files, which Microsoft puts at 35% of total savings. One file, data/index.ts, held 13 namespace imports in a dispatch table and accounted for 324 of those bytes on its own.
The post adds a qualification: namespace imports used only for direct property access cause no problem. The cost appears only "when the namespace itself gets passed around as a value."
Minifier settings
The second largest gain, 301 bytes, came from configuration rather than code. The agent tested every Terser compress and mangle option it could find. "Most did nothing," according to the post. Three settings worked: passes set to 3, hoist_vars enabled, and freeze disabled on Rollup's IIFE outputs.
Several others produced no gain, including passes set to 4, unsafe_math, unsafe_undefined, unsafe_arrows, reduce_vars, wrap_iife and an ECMAScript 2017 target in the compress settings. Property mangling was the only option that caused real problems, because shortened names collided with DOM property names.
Template literals, large blocks and dead functions
Because clarity.js targets ES5, the 2009 edition of JavaScript, TypeScript compiles a template literal such as ${a}${b} into a chain of .concat() method calls. Writing a plain a + b compiles to a+b. Replacing every template literal in the codebase saved 110 bytes.
Another 109 bytes came from a 27-line block in baseline.ts that copied buffer properties one at a time; a single Object.assign({}, buffer) call replaced it. Removing whole functions saved 84 bytes. A 12-line routine in compress.ts that manually read chunks from a ReadableStream was replaced by a one-line call to the browser's Response API, saving 44 bytes. A parseSignals() wrapper that only called JSON.parse() inside a try/catch, when the caller already had its own try/catch, accounted for another 20. The post does not itemize the remaining 20 bytes in that category.
Why cleaner code made the download bigger
The more striking finding concerns what did not work. According to the post, the project showed that "many changes that look more efficient in source code don't actually produce a smaller script once it's compressed."
Why would shorter code produce a bigger file? The reason lies in how gzip operates. It finds repeated byte sequences and replaces them with short references, so code that repeats itself is close to free. Every new function name, novel pattern or unique string, by contrast, becomes a fresh entry that costs real bytes.
The team learned this the hard way. clarity.js contained four identical six-line blocks of coordinate-tracking code, copied across the cases of a switch statement. Extracting them into a shared coordinates() helper - the kind of refactoring most style guides recommend - cut the raw file by 264 bytes. "Gzipped size went up by 23 bytes," the post states. Gzip had already compressed the four duplicate blocks "down to almost nothing," while the helper introduced a new function name, a new call signature and four new call sites.
Similar attempts went the wrong way elsewhere:
- A shared coordinates() helper added 23 bytes.
- A dim() helper for width and height added 13 bytes.
- Hoisting shared arrays to module scope added 2 bytes.
- Using the ||= logical assignment operator added 3 bytes.
The last example is the most counterintuitive. "It's literally shorter syntax, but it's a rare byte pattern in the output," according to Nair. The older x = x || defaultValue form appears throughout the code, so gzip already treats it as a known pattern. "The 'modern' version is actually worse," the post concludes.
Size alone was not the rule, though. Small extractions hurt, but very large unique blocks of 20 lines or more behaved differently, being too big for gzip to handle efficiently. That is why the 27-line baseline.ts block was worth collapsing while the six-line coordinate blocks were not.
The 2,308-byte saving that stayed on the shelf
The single most effective change found during the project was one Microsoft chose not to release. Raising the TypeScript compilation target from ES5 to ES2017 removed the __awaiter and __generator polyfills, multi-line helper functions that TypeScript injects so that async/await code can run on older JavaScript engines. Combined with an ES2020 target, which enables native optional chaining and nullish coalescing, the move saved 2,308 gzip bytes.
That is "almost double everything else combined," according to the post. By PPC Land's calculation, it is 1.84 times the 1,257 bytes that did ship, and roughly 8% of the script's implied starting size on its own.
"Ultimately, we couldn't ship this optimization because of compatibility requirements," Nair writes. Clarity runs on all kinds of websites, including Angular applications that use Zone.js. That library patches the browser's Promise object and expects the ES5 generator-based form of async/await. "When we emit native async/await, Zone.js can't intercept it, and Angular's change detection breaks silently," the post explains.
Silently is the operative word. A third-party analytics script that stopped the host application from updating its own interface, without throwing a visible error, would be hard for a site owner to trace back to its source. Microsoft's choice reflects the constraint every vendor tag carries: it has to run on code it does not control.
What the post does not say
Several details are absent. Microsoft does not give a date on which the smaller script reached production websites, or a version number. It reports gzip sizes only, with no figures for other compression formats or for download or execution time. And it offers no measurement of the change's effect on page performance metrics such as load time or responsiveness.
The post closes with six recommendations for other engineering teams: check namespace imports, test minifier options one at a time, remove whole functions where possible, avoid extracting small helpers, measure gzipped rather than raw size, and automate the process.
Why this matters for marketers and publishers
For most marketers, the inner workings of a bundler are invisible. The scripts they add to a page are not. Every analytics, advertising and consent tag adds bytes that a visitor's browser must download, parse and run before or alongside the content, and the cost lands on site speed metrics that publishers and advertisers increasingly track. Core Web Vitals, Google's page experience measures, treat a page as responsive when interactions complete in 200 milliseconds or less, and the time spent on third-party JavaScript feeds into that budget along with network latency.
The Clarity post makes an argument that marketers have met in other forms: the number that looks like progress is not always the one that matters. In November 2025, a case PPC Land reported showed that applying lazy loading to every image on a site lifted its PageSpeed score from 65 to 92 while traffic fell 20%, because the main image took 4.2 seconds to appear instead of 1.8. Microsoft's coordinates() helper is the same pattern in miniature: 264 bytes saved on paper, 23 bytes added in the file browsers actually receive.
Script loading has been on Google's agenda as well. When Google announced on May 20, 2026 that Google Tag Manager and the Google tag were merging, it included an opt-in container optimization that removes the separate gtag.js load for data transmission. PPC Land has also documented how Google Tag Manager in 2026 is far more complex than most marketers think, with layers of triggers, variables and consent dependencies sitting behind each container.
For publishers in the Microsoft Audience Network, clarity.js is no longer optional. Since the November 2025 requirement, a page without the script cannot generate billable Microsoft Advertising clicks, which makes its weight a cost those publishers carry by default. A 4.5% reduction is modest in absolute terms - a little over a kilobyte - but it applies to every page view on every site where the script loads.
The project also adds to a growing body of evidence on how software teams deploy AI agents. PPC Land reported in January 2026 on why developers had become obsessed with Claude Code, and in July 2026 on WebKit shipping a Safari MCP server with 17 tools for AI debugging agents, including tools for performance analysis. Clarity's case is narrow, and unusually measurable for an account of agentic AI in engineering. The goal was a single number, the test suite acted as the safety check, and every change was reversible. The trade-off between size and compatibility was a different matter. The post presents that call, worth more bytes than every accepted change put together, as the team's own decision on compatibility grounds.
Not all of Clarity's recent work depends on the browser script. When the product added bot activity tracking on January 21, 2026, it drew on server-side logs from supported content delivery networks instead. Its AI visibility features, including a Query Topics beta in July and, from September 29, the ability to edit which terms count as branded AI queries, track how AI assistants cite a site. The heatmaps and session recordings the product was built on still come from clarity.js.
Timeline
- January 13, 2025 - Microsoft Clarity adds Google Ads data analysis to behavioral analytics tools
- July 30, 2025 - Microsoft Clarity simplifies WordPress setup with a streamlined plugin
- August 27, 2025 - Microsoft Clarity announces cookie consent enforcement for the EEA, UK and Switzerland
- October 31, 2025 - Clarity consent enforcement takes full effect
- November 7, 2025 - Lazy loading case shows a PageSpeed score rising from 65 to 92 while traffic drops 20%
- November 11, 2025 - Microsoft Advertising requires Clarity for third-party publishers
- January 3, 2026 - A Google engineer's post on Claude Code draws 5.4 million views on X
- January 21, 2026 - Microsoft Clarity adds bot activity tracking
- May 20, 2026 - Google announces the merger of Google Tag Manager and the Google tag
- July 1, 2026 - WebKit ships a Safari MCP server with 17 tools for AI debugging agents
- July 2026 - Microsoft Clarity launches a Query Topics beta for AI citation queries
- September 29, 2026 - Microsoft Clarity lets brands edit what counts as a branded AI query
- October 29, 2026 - Microsoft publishes "How We Made clarity.js 4.5% Smaller Without Sacrificing Compatibility," reporting a 1,257-byte gzip reduction after more than 50 agent-run experiments and an unshipped 2,308-byte saving
Related PPC Land coverage
- Microsoft Advertising requires Clarity for third-party publishers - Clicks from third-party publisher pages without Clarity installed became non-billable from November 11, 2025.
- Microsoft Clarity enforces cookie consent requirements across Europe - Consent signal enforcement for EEA, UK and Swiss sessions from October 31, 2025.
- Microsoft Clarity adds Google Ads data analysis to behavioral analytics tools - Session recordings and heatmaps for visitors arriving from Google Ads, generally available from January 2025.
- Microsoft Clarity vs. Google Analytics 4: a detailed comparison - How Clarity's behavioral data compares with GA4's reporting.
- Microsoft Clarity exposes AI bot traffic with new visibility dashboard - Bot activity tracking built on server-side logs rather than the browser script.
- Microsoft Clarity lets brands edit what counts as a branded AI query - The September 2026 Brand Terms control in Clarity's AI Visibility settings.
- Lazy loading implementation causes 20% traffic drop despite PageSpeed gains - A case where a better speed score coincided with worse real-world loading and lower traffic.
- Google Tag Manager and Google tag are merging - what actually changes - Google's container changes, including an opt-in optimization that removes a separate gtag.js load.
- Google Tag Manager in 2026: far more complex than most marketers think - The layers of tags, triggers and consent rules behind a typical container.
- Why developers are obsessed with Claude Code - The January 2026 surge of interest in AI coding agents among professional developers.
- WebKit ships Safari MCP server with 17 tools for AI debugging agents - Browser tooling that lets AI agents inspect pages, run JavaScript and analyze performance.
Summary
Who: Microsoft's Clarity engineering team, in a blog post by Manu Nair, using pi, an open-source AI coding agent, with the pi-autoresearch experiment extension. The change affects every website that loads Clarity, including third-party publishers required to run it under Microsoft Advertising rules.
What: clarity.js, the script behind Clarity's heatmaps and session recordings, became 1,257 gzip bytes smaller, a 4.5% reduction, without losing functionality. The largest share, 444 bytes, came from replacing namespace imports, followed by 301 bytes from minifier settings. Several refactorings that shrank the raw source made the compressed file larger. A further 2,308-byte saving from targeting newer JavaScript was not shipped because it breaks Angular applications that use Zone.js.
When: Microsoft published the account on October 29, 2026. The post does not give the date the smaller script reached production.
Where: The work applies to clarity.js wherever Clarity runs. Microsoft describes that footprint as billions of web pages.
Why: Every byte in a third-party script is downloaded by each visitor on every page where it loads. Microsoft automated the search because individual savings of 5 to 50 bytes were too small to justify human time, while 35-second build-and-measure cycles let an agent test 100 ideas in under an hour.
Discussion