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
18 changes: 16 additions & 2 deletions next-sitemap.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
const i18nConfig = require("./i18n.config.json")
const locales = i18nConfig.map(({ code }) => code)

const defaultLocale = "en"

/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.SITE_URL || "https://ethereum.org",
generateRobotsTxt: true,
transform: async (_, path) => {
const rootPath = path.split("/")[1]
if (path.endsWith("/404")) return null
const isDefaultLocale = !locales.includes(rootPath) || rootPath === "en"
const isDefaultLocale =
!locales.includes(rootPath) || rootPath === defaultLocale

// Strip default-locale (en) prefix from paths; drop the `/en` root entry
let loc = path
if (rootPath === defaultLocale) {
// Drop the `/en` root entry to avoid duplicating `/`
if (path === `/${defaultLocale}` || path === `/${defaultLocale}/`)
return null
const defaultLocalePrefix = new RegExp(`^/${defaultLocale}(/|$)`)
loc = path.replace(defaultLocalePrefix, "/")
}

return {
loc: path,
loc,
changefreq: isDefaultLocale ? "weekly" : "monthly",
priority: isDefaultLocale ? 0.7 : 0.5,
}
Expand Down
8 changes: 6 additions & 2 deletions src/components/Matomo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { usePathname } from "next/navigation"
import { init, push } from "@socialgouv/matomo-next"

import { IS_PREVIEW_DEPLOY } from "@/lib/utils/env"
import { normalizePathForMatomo } from "@/lib/utils/matomo"

export default function Matomo() {
const pathname = usePathname()
Expand Down Expand Up @@ -40,8 +41,11 @@ export default function Matomo() {
return setPreviousPath(pathname)
}

push(["setReferrerUrl", `${previousPath}`])
push(["setCustomUrl", pathname])
const normalizedPreviousPath = normalizePathForMatomo(previousPath)
const normalizedPathname = normalizePathForMatomo(pathname)

push(["setReferrerUrl", normalizedPreviousPath])
push(["setCustomUrl", normalizedPathname])
push(["deleteCustomVariables", "page"])
setPreviousPath(pathname)
// In order to ensure that the page title had been updated,
Expand Down
1 change: 1 addition & 0 deletions src/i18n/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const routing = defineRouting({
locales: LOCALES_CODES,
defaultLocale: DEFAULT_LOCALE,
localeCookie: false,
localePrefix: "as-needed",
})

// Lightweight wrappers around Next.js' navigation APIs
Expand Down
26 changes: 25 additions & 1 deletion src/lib/utils/matomo.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import { push } from "@socialgouv/matomo-next"

import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"

import { IS_PROD } from "./env"

export const MATOMO_LS_KEY = "ethereum-org.matomo-opt-out"

/**
* Normalizes paths to ensure consistent Matomo tracking.
* With localePrefix: "as-needed", English paths don't have /en prefix,
* but we want to track them as /en paths for analytics consistency.
*/
export const normalizePathForMatomo = (pathname: string): string => {
const hasLocalePrefix = LOCALES_CODES.some((locale) =>
pathname.startsWith(`/${locale}/`)
)

if (hasLocalePrefix) {
return pathname
}

// For paths without locale prefix (English content), add /en prefix
return `/${DEFAULT_LOCALE}${pathname}`
}
Comment on lines +9 to +25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Edge case: locale root without trailing slash is misdetected.

startsWith(\/${locale}/`)misses/${locale}(no trailing slash), causing accidental/endouble-prefixing (e.g.,"/es""/en/es"`).

Apply:

-export const normalizePathForMatomo = (pathname: string): string => {
-  const hasLocalePrefix = LOCALES_CODES.some((locale) =>
-    pathname.startsWith(`/${locale}/`)
-  )
+export const normalizePathForMatomo = (pathname: string): string => {
+  const hasLocalePrefix = LOCALES_CODES.some(
+    (locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)
+  )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Normalizes paths to ensure consistent Matomo tracking.
* With localePrefix: "as-needed", English paths don't have /en prefix,
* but we want to track them as /en paths for analytics consistency.
*/
export const normalizePathForMatomo = (pathname: string): string => {
const hasLocalePrefix = LOCALES_CODES.some((locale) =>
pathname.startsWith(`/${locale}/`)
)
if (hasLocalePrefix) {
return pathname
}
// For paths without locale prefix (English content), add /en prefix
return `/${DEFAULT_LOCALE}${pathname}`
}
export const normalizePathForMatomo = (pathname: string): string => {
const hasLocalePrefix = LOCALES_CODES.some(
(locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)
)
if (hasLocalePrefix) {
return pathname
}
// For paths without locale prefix (English content), add /en prefix
return `/${DEFAULT_LOCALE}${pathname}`
}
🤖 Prompt for AI Agents
In src/lib/utils/matomo.ts around lines 9 to 25, the locale detection uses
startsWith(`/${locale}/`) which misses the exact locale root (e.g., "/es") and
causes double-prefixing; update the hasLocalePrefix check to treat either an
exact match (`pathname === \`/${locale}\``) or a prefix match
(`pathname.startsWith(\`/${locale}/\`)`) as having a locale so the function
returns the original pathname for both `/locale` and `/locale/...` cases and
only prefixes `/${DEFAULT_LOCALE}` for truly locale-less paths.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

pathname is what it is, I don't think this matters... the helper function here just slips in the English prefix as-needed


export interface MatomoEventOptions {
eventCategory: string
eventAction: string
Expand All @@ -27,6 +47,10 @@ export const trackCustomEvent = ({
if (isOptedOut) return

// Set custom URL removing any query params or hash fragments
window && push([`setCustomUrl`, window.location.href.replace(/[?#].*$/, "")])
if (window) {
const normalizedPathname = normalizePathForMatomo(window.location.pathname)
const normalizedUrl = window.location.origin + normalizedPathname
push([`setCustomUrl`, normalizedUrl])
}
push([`trackEvent`, eventCategory, eventAction, eventName, eventValue])
}
4 changes: 3 additions & 1 deletion src/lib/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export const addSlashes = (href: string): string => {
}

export const getFullUrl = (locale: string | undefined, path: string) =>
addSlashes(new URL(join(locale || DEFAULT_LOCALE, path), SITE_URL).href)
DEFAULT_LOCALE === locale || !locale
? addSlashes(new URL(path, SITE_URL).href)
: addSlashes(new URL(join(locale, path), SITE_URL).href)

// Remove trailing slash from slug and add leading slash
export const normalizeSlug = (slug: string) => {
Expand Down