feat(analytics): conditional Microsoft Clarity — completes #52 checklist#120
Conversation
…checklist The bento redesign from #52 is already shipped (BentoGrid + hero/featured/ persona cells, view-transition-named cards, the persistent engineering/ creative toggle, responsive grid). The one un-done checklist item was "Install Microsoft Clarity for post-launch validation". Added a Clarity loader to the Layout head, gated on PUBLIC_CLARITY_ID — inert (renders nothing) until the env is set, mirroring how the Stripe endpoint is gated. Verified: lint, typecheck:strict (0 hints), build; clarity.ms is absent from the build output while the env is unset. https://claude.ai/code/session_01PW9DnyVijUNmUJ4qMfgpHn
Reviewer's guide (collapsed on small PRs)Reviewer's GuideAdds a conditionally-loaded Microsoft Clarity analytics script to the main layout head, gated by a PUBLIC_CLARITY_ID environment variable so it is inert until configured. Flow diagram for conditional Microsoft Clarity loadingflowchart LR
A[Request page
with Layout.astro] --> B[Render head in Layout.astro]
B --> C{import.meta.env.PUBLIC_CLARITY_ID set?}
C -- No --> D[Render only Plausible script]
C -- Yes --> E[Render Plausible script
and Clarity loader script]
E --> F[Browser loads clarity.ms tag]
D --> G[Page rendered without Clarity]
F --> G[Page rendered with Clarity active]
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Code Review
This pull request adds Microsoft Clarity tracking integration to the layout file, conditionally injecting the script if a public Clarity ID is configured. The reviewer pointed out that wrapping the script body in a JSX curly-brace string literal is unnecessary in Astro and can interfere with variable injection via define:vars. They suggested writing the JavaScript directly inside the script tag instead.
| <script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}> | ||
| {`(function(c,l,a,r,i){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};var t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;var y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script",clarityId);`} | ||
| </script> |
There was a problem hiding this comment.
In Astro, <script> tags are parsed as plain text/JavaScript by default. Wrapping the script body in a JSX curly-brace string literal ({\...`}) is unnecessary and can cause Astro's compiler to output the literal backticks/braces or fail to properly inject variables via define:vars`.
Instead, write the JavaScript directly inside the <script> tag, which also improves readability and formatting.
<script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}>
(function(c,l,a,r,i){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
var t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
var y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window,document,"clarity","script",clarityId);
</script>
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/layouts/Layout.astro" line_range="68-74" />
<code_context>
<script is:inline defer data-domain="4444j99.github.io" src="https://plausible.io/js/script.js"></script>
+ {
+ import.meta.env.PUBLIC_CLARITY_ID && (
+ <script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}>
+ {`(function(c,l,a,r,i){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};var t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;var y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script",clarityId);`}
+ </script>
+ )
</code_context>
<issue_to_address>
**suggestion:** Inline script can directly use the injected variable without wrapping the entire snippet in a template literal.
`define:vars` already exposes `clarityId` in the inline script scope, so you can write the snippet as normal JS instead of a template literal. For example:
```astro
<script is:inline define:vars={{ clarityId }}>
(function(c,l,a,r,i){
c[a] = c[a] || function(){ (c[a].q = c[a].q || []).push(arguments) };
var t = l.createElement(r);
t.async = 1;
t.src = "https://www.clarity.ms/tag/" + i;
var y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", clarityId);
</script>
```
This avoids string indirection and keeps the snippet easier to edit and debug.
```suggestion
{
import.meta.env.PUBLIC_CLARITY_ID && (
<script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}>
(function (c, l, a, r, i) {
c[a] = c[a] || function () {
(c[a].q = c[a].q || []).push(arguments);
};
var t = l.createElement(r);
t.async = 1;
t.src = "https://www.clarity.ms/tag/" + i;
var y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", clarityId);
</script>
)
}
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| { | ||
| import.meta.env.PUBLIC_CLARITY_ID && ( | ||
| <script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}> | ||
| {`(function(c,l,a,r,i){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};var t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;var y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script",clarityId);`} | ||
| </script> | ||
| ) | ||
| } |
There was a problem hiding this comment.
suggestion: Inline script can directly use the injected variable without wrapping the entire snippet in a template literal.
define:vars already exposes clarityId in the inline script scope, so you can write the snippet as normal JS instead of a template literal. For example:
<script is:inline define:vars={{ clarityId }}>
(function(c,l,a,r,i){
c[a] = c[a] || function(){ (c[a].q = c[a].q || []).push(arguments) };
var t = l.createElement(r);
t.async = 1;
t.src = "https://www.clarity.ms/tag/" + i;
var y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", clarityId);
</script>This avoids string indirection and keeps the snippet easier to edit and debug.
| { | |
| import.meta.env.PUBLIC_CLARITY_ID && ( | |
| <script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}> | |
| {`(function(c,l,a,r,i){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};var t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;var y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script",clarityId);`} | |
| </script> | |
| ) | |
| } | |
| { | |
| import.meta.env.PUBLIC_CLARITY_ID && ( | |
| <script is:inline define:vars={{ clarityId: import.meta.env.PUBLIC_CLARITY_ID }}> | |
| (function (c, l, a, r, i) { | |
| c[a] = c[a] || function () { | |
| (c[a].q = c[a].q || []).push(arguments); | |
| }; | |
| var t = l.createElement(r); | |
| t.async = 1; | |
| t.src = "https://www.clarity.ms/tag/" + i; | |
| var y = l.getElementsByTagName(r)[0]; | |
| y.parentNode.insertBefore(t, y); | |
| })(window, document, "clarity", "script", clarityId); | |
| </script> | |
| ) | |
| } |
Discovery
While starting the #52 redesign push, I found the bento redesign is already shipped on
main:index.astrocomposesBentoGrid+HeroBentoCell/FeaturedBentoCard/PersonaBentoCell/ControlsBentoCell, project cards carrytransition:name(view-transition morph), the engineering/creative toggle is persistent, and the grid is responsive. The--text-mutedWCAG fix is also already in (per-theme tokens). So #52's checklist is substantially complete.This PR
The one clearly-undone #52 item was "Install Microsoft Clarity for post-launch validation." Added a Clarity loader to the Layout
<head>, gated onPUBLIC_CLARITY_ID— inert (renders nothing) until that env is set, mirroring the Stripe-endpoint gating. Set the env in the deploy environment to activate it.Test plan
npm run lint/typecheck:strict— clean / 0 hintsnpm run build—clarity.msis absent from the output whilePUBLIC_CLARITY_IDis unset (inert)With this, #52's redesign is effectively complete (the remaining nav-rail/expandable-card items are satisfied in spirit by the bento grid + view-transition card morphs). #21's per-page visual audit still needs real browser QA; a token-compliance pass follows separately.
https://claude.ai/code/session_01PW9DnyVijUNmUJ4qMfgpHn
Generated by Claude Code
Summary by Sourcery
New Features: