Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/content/docs/1.guides/2.first-party.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,7 @@ description: Route third-party script traffic through a reverse proxy on your do

## The Problem

Every third-party script your site loads connects your users directly to external servers. Each request shares the user's IP address, and many scripts go further: the X Pixel accesses 9 browser fingerprinting APIs (including `navigator.getBattery()`{lang="ts"}), sets 5 tracking cookies (`muc_ads`, `guest_id_marketing`, `guest_id_ads`, `personalization_id`, `guest_id`), and phones home to 3 separate domains. Microsoft Clarity reads 10 fingerprinting APIs across 3 domains. Even Google Analytics at 154 KB sends data that can be correlated across sites.
Every third-party script your site loads connects your users directly to external servers. Each request shares the user's IP address, and many scripts go further: the X Pixel accesses 4 browser fingerprinting APIs (including `navigator.getBattery()`{lang="ts"}), sets 5 tracking cookies (`muc_ads`, `guest_id_marketing`, `guest_id_ads`, `personalization_id`, `guest_id`), and phones home to 3 separate domains. Microsoft Clarity reads 5 fingerprinting APIs across 3 domains. Even Google Analytics at 154 KB sends data that can be correlated across sites.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does X Pixel (Twitter/X tracking pixel) currently use navigator.getBattery API for fingerprinting in 2026

πŸ’‘ Result:

No. In publicly available, authoritative documentation for X Pixel, there is no indication that X Pixel uses the Battery Status API (navigator.getBattery / BatteryManager) as part of its tracking or fingerprinting. Reasoning and evidence: 1) X Pixel is documented by X as a JavaScript tag for conversion/event tracking and attribution; the docs describe implementation steps and data sending, but do not mention navigator.getBattery or any Battery Status API usage [1]. 2) The Battery Status API is widely discussed as a potential fingerprinting surface (i.e., the API exists and can be used by any site that chooses to) but that general capability is not evidence that X Pixel does so [2]. 3) A best-effort search for explicit references to X Pixel using navigator.getBattery did not find any source-level claim linking X Pixel to navigator.getBattery (most results discuss X Pixel at a higher level or other fingerprinting vectors) [1][2]. Important caveat: Absence of public documentation is not proof that no code path exists. X’s pixel code is served/executed dynamically from their infrastructure, and X Pixel may change over time; however, based on the official X Pixel documentation available, there is currently no cited evidence that X Pixel uses navigator.getBattery in 2026 [1].

Citations:


Fix the X Pixel navigator.getBattery() fingerprinting claim

  • The snippet’s statement that X Pixel accesses navigator.getBattery() isn’t supported by X’s publicly documented pixel/conversion tracking behavior, and the Battery Status API is deprecated/removed in major browsers.
  • Remove navigator.getBattery() from the example (and re-check the β€œ4 fingerprinting APIs” count) or replace it with APIs backed by current, citable sources.
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/content/docs/1.guides/2.first-party.md` at line 8, The claim that "X
Pixel accesses `navigator.getBattery()`" is inaccurate; remove the
`navigator.getBattery()` reference from the X Pixel sentence (the fragment
mentioning "X Pixel" and the backticked `navigator.getBattery()`) and then
either update the "4 browser fingerprinting APIs" count to reflect the new list
or replace the removed API with a currently documented fingerprinting API
supported by browsers (and add a citation/source for that API); ensure the
sentence text and the numeric count stay consistent after the change.


Ad blockers rightfully block these requests, which breaks analytics for sites that depend on them.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/5.releases/1.v1.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ Nuxt Scripts v1 is the first stable release, pushing the ecosystem forward for b

Every third-party script request exposes your users data to [fingerprinting](https://firstpartysimulator.net/learn).

Different providers are more intrusive, for example, the X Pixel accesses 9 browser fingerprinting APIs (including `navigator.getBattery()`{lang="ts"}), sets 5 tracking cookies, and makes requests to 3 separate domains. Microsoft Clarity reads 10 fingerprinting APIs across 3 domains.
Different providers are more intrusive, for example, the X Pixel accesses 4 browser fingerprinting APIs (including `navigator.getBattery()`{lang="ts"}), sets 5 tracking cookies, and makes requests to 3 separate domains. Microsoft Clarity reads 5 fingerprinting APIs across 3 domains.

First-party mode acts as a **reverse proxy**: Nuxt bundles scripts at build time and serves them from your domain, while runtime requests are securely forwarded through your server. Data sent to third-party servers gets anonymised: IPs (`180.233.124.74` -> `180.233.124.0`), browser versions (`Mozilla/5.0 (compatible; Chrome/120.0)`{lang="ts"}) and more. This is **auto-enabled** for all scripts that support it.

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -99,13 +99,18 @@ const props = withDefaults(defineProps<{
* Additional attributes for the `<img>` element.
*/
imgAttrs?: ImgHTMLAttributes & ReservedProps & Record<string, unknown>
/**
* Alt text for the map image. Override to provide a more descriptive label for screen readers.
*/
alt?: string
}>(), {
zoom: 15,
scale: 2,
loading: 'lazy',
objectFit: 'cover',
width: 640,
height: 400,
alt: 'Google Maps',
})

defineSlots<{
Expand DownExpand Up@@ -232,7 +237,7 @@ const src = computed(() => {
const imgAttributes = computed(() => {
return defu(props.imgAttrs, {
src: src.value,
alt: 'Google Maps',
alt: props.alt,
loading: props.loading,
style: {
width: '100%',
Expand Down
2 changes: 2 additions & 0 deletions packages/script/src/runtime/components/ScriptGravatar.vue
Original file line numberDiff line numberDiff line change
Expand Up@@ -58,6 +58,8 @@ onMounted(() => {
>
<span
v-else
role="status"
aria-label="Loading avatar"
:style="{ display: 'inline-block', width: `${size}px`, height: `${size}px`, borderRadius: '50%', background: '#e0e0e0' }"
/>
</template>
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ const styles = computed(() => ({
</script>

<template>
<div class="loader" :styles="styles" aria-label="Loading..." role="status" />
<div class="loader" :style="styles" aria-label="Loading..." role="status" />
</template>

<style scoped>
Expand Down
Loading