Skip to content

feat(analytics): conditional Microsoft Clarity — completes #52 checklist#120

Merged
4444J99 merged 1 commit into
mainfrom
feat/clarity-analytics
May 26, 2026
Merged

feat(analytics): conditional Microsoft Clarity — completes #52 checklist#120
4444J99 merged 1 commit into
mainfrom
feat/clarity-analytics

Conversation

@4444J99
Copy link
Copy Markdown
Owner

@4444J99 4444J99 commented May 26, 2026

Discovery

While starting the #52 redesign push, I found the bento redesign is already shipped on main: index.astro composes BentoGrid + HeroBentoCell/FeaturedBentoCard/PersonaBentoCell/ControlsBentoCell, project cards carry transition:name (view-transition morph), the engineering/creative toggle is persistent, and the grid is responsive. The --text-muted WCAG 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 on PUBLIC_CLARITY_IDinert (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 hints
  • npm run buildclarity.ms is absent from the output while PUBLIC_CLARITY_ID is 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:

  • Integrate Microsoft Clarity tracking script into the main layout, enabled only when a public Clarity ID environment variable is set.

…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
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 26, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds 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 loading

flowchart 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]
Loading

File-Level Changes

Change Details Files
Conditionally inject Microsoft Clarity tracking into the global layout head, gated by an environment variable so it only loads in configured environments.
  • Extend the global layout head to include a new inline script block that checks for the presence of PUBLIC_CLARITY_ID via import.meta.env.
  • When PUBLIC_CLARITY_ID is set, define clarityId as an inline script variable using define:vars and inject the official Clarity loader snippet pointing at clarity.ms/tag/{clarityId}.
  • Ensure that when PUBLIC_CLARITY_ID is not set, the Clarity script tag and network request are not emitted in the built output, keeping the integration inert by default.
src/layouts/Layout.astro

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/layouts/Layout.astro
Comment on lines +70 to +72
<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>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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>

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/layouts/Layout.astro
Comment on lines +68 to +74
{
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>
)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
{
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>
)
}

@4444J99 4444J99 merged commit eb9bf5c into main May 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants