Skip to content

feat(analytics): add Microsoft Clarity to the frontend - #11

Merged
Elias-3817 merged 1 commit into
mainfrom
feat/microsoft-clarity-analytics
Jul 29, 2026
Merged

feat(analytics): add Microsoft Clarity to the frontend#11
Elias-3817 merged 1 commit into
mainfrom
feat/microsoft-clarity-analytics

Conversation

@Elias-3817

Copy link
Copy Markdown

No description provided.

Render the Clarity tag from the root app layout when
NEXT_PUBLIC_CLARITY_PROJECT_ID is set, following the existing Facebook
pixel component. Document the variable in .env.example.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add Microsoft Clarity analytics tag gated by NEXT_PUBLIC_CLARITY_PROJECT_ID

✨ Enhancement ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Add a Microsoft Clarity script component rendered from the root app layout.
• Gate Clarity loading behind NEXT_PUBLIC_CLARITY_PROJECT_ID for easy enable/disable.
• Document the new environment variable in .env.example for build-time configuration.
Diagram

graph TD
  A["AppLayout"] --> B["ClarityComponent"] --> C{{"Microsoft Clarity"}}
  A --> D["FacebookComponent"] --> E{{"Meta Pixel"}}
  F[("NEXT_PUBLIC_CLARITY_PROJECT_ID")] --> B
  G[".env.example"] --> F

  subgraph Legend
    direction LR
    _cmp["UI component"] ~~~ _cfg[("Config / env")] ~~~ _ext{{"External service"}}
  end
Loading
High-Level Assessment

The approach is consistent with the existing analytics pattern (FacebookComponent): a small client component using next/script and an env-var gate. Alternatives like injecting via /metadata or centralizing via a tag manager add complexity without clear benefit for this single integration.

Files changed (3) +24 / -0

Enhancement (2) +20 / -0
layout.tsxRender ClarityComponent from the root AppLayout +2/-0

Render ClarityComponent from the root AppLayout

• Imports ClarityComponent and renders it alongside existing analytics components so the Clarity tag is injected application-wide when enabled.

apps/frontend/src/app/(app)/layout.tsx

clarity.component.tsxAdd client-side Microsoft Clarity Script injector +18/-0

Add client-side Microsoft Clarity Script injector

• Introduces a client component that conditionally injects the Microsoft Clarity bootstrap snippet via next/script (afterInteractive) when NEXT_PUBLIC_CLARITY_PROJECT_ID is present.

apps/frontend/src/components/layout/clarity.component.tsx

Other (1) +4 / -0
.env.exampleDocument NEXT_PUBLIC_CLARITY_PROJECT_ID env var for Clarity enablement +4/-0

Document NEXT_PUBLIC_CLARITY_PROJECT_ID env var for Clarity enablement

• Adds documentation for the public Clarity project id variable, noting it disables analytics when empty and must be set at build time due to inlining.

.env.example

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Unescaped env in script 🐞 Bug ⛨ Security
Description
ClarityComponent interpolates NEXT_PUBLIC_CLARITY_PROJECT_ID into an inline <Script> JavaScript
string literal without escaping, so values containing quotes, backslashes, newlines, or </script>
can break parsing or inject extra script. Because NEXT_PUBLIC_* values are inlined at build time,
the threat model is a compromised/malicious build/deploy configuration rather than an end-user
runtime input, but it can still affect every page load.
Code

apps/frontend/src/components/layout/clarity.component.tsx[R10-16]

+    <Script strategy="afterInteractive" id="ms-clarity">
+      {`(function(c,l,a,r,i,t,y){
+c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
+t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
+y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
+})(window,document,"clarity","script","${process.env.NEXT_PUBLIC_CLARITY_PROJECT_ID}");`}
+    </Script>
Evidence
The Clarity loader script directly embeds the env var inside a quoted JS string in an inline script
block, with no escaping/validation. The .env.example explicitly notes this value is inlined at build
time, clarifying the relevant threat model and why malformed values would ship to clients.

apps/frontend/src/components/layout/clarity.component.tsx[5-16]
.env.example[100-102]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`NEXT_PUBLIC_CLARITY_PROJECT_ID` is inserted into an inline script as a quoted JS string without escaping. If the value contains `"`, `\`, line terminators, or `</script>`, the resulting HTML/JS can break or be altered.

## Issue Context
This value is **inlined at build time** (not runtime), so the main risk is a malformed/malicious build-time env value impacting all served pages.

## Fix Focus Areas
- apps/frontend/src/components/layout/clarity.component.tsx[6-16]

## Suggested fix
- Serialize the value safely and avoid manual quoting, e.g.:
 - `const pid = process.env.NEXT_PUBLIC_CLARITY_PROJECT_ID;`
 - Validate format defensively (e.g. `/^[A-Za-z0-9_-]+$/`) and `return null` if invalid.
 - Inject as `...(window,document,"clarity","script",${JSON.stringify(pid)});` (note: **no surrounding quotes** around the placeholder).
- (Optional) Add a short comment explaining the expected Clarity project id format.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread apps/frontend/src/components/layout/clarity.component.tsx
@Elias-3817
Elias-3817 merged commit de284da into main Jul 29, 2026
1 check passed
@Elias-3817
Elias-3817 deleted the feat/microsoft-clarity-analytics branch July 29, 2026 16:18
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.

1 participant