Skip to content

Commit 6a092fc

Browse files
authored
Merge pull request #182 from fbosch/fix/analytics-consent-tracking
fix(analytics): allow production hostname fallback when env is missing
2 parents 717f314 + 29e0dd1 commit 6a092fc

3 files changed

Lines changed: 52 additions & 11 deletions

File tree

src/components/analytics/ConditionalAnalytics.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dynamic from "next/dynamic";
44
import { useLocalStorage } from "@/hooks/useLocalStorage";
55
import { useMounted } from "@/hooks/useMounted";
6+
import { isAnalyticsProductionEnvironment } from "@/lib/analytics/trackEvent";
67

78
const SpeedInsights = dynamic(
89
() => import("@vercel/speed-insights/next").then((mod) => mod.SpeedInsights),
@@ -39,9 +40,7 @@ export function ConditionalAnalytics() {
3940

4041
// Only render Analytics if component has mounted and user has given consent
4142
// Disable analytics in development and preview environments
42-
const isProduction =
43-
process.env.NODE_ENV === "production" &&
44-
process.env.NEXT_PUBLIC_VERCEL_ENV === "production";
43+
const isProduction = isAnalyticsProductionEnvironment();
4544

4645
if (mounted === false || !preferences.analytics || !isProduction) {
4746
return null;
@@ -59,9 +58,7 @@ export function ConditionalSpeedInsights() {
5958

6059
// Only render SpeedInsights if component has mounted and user has given consent
6160
// Disable speed insights in development and preview environments
62-
const isProduction =
63-
process.env.NODE_ENV === "production" &&
64-
process.env.NEXT_PUBLIC_VERCEL_ENV === "production";
61+
const isProduction = isAnalyticsProductionEnvironment();
6562

6663
if (mounted === false || !preferences.speedInsights || !isProduction) {
6764
return null;

src/lib/analytics/__tests__/trackEvent.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe("analytics transport wrapper", () => {
6565
});
6666
});
6767

68-
it("checks production and vercel production env", () => {
68+
it("checks production environment with safe hostname fallback", () => {
6969
expect(
7070
isAnalyticsProductionEnvironment({
7171
NODE_ENV: "production",
@@ -92,6 +92,24 @@ describe("analytics transport wrapper", () => {
9292
NODE_ENV: "production",
9393
}),
9494
).toBe(false);
95+
96+
expect(
97+
isAnalyticsProductionEnvironment(
98+
{
99+
NODE_ENV: "production",
100+
},
101+
"fusion.nuzlocke.io",
102+
),
103+
).toBe(true);
104+
105+
expect(
106+
isAnalyticsProductionEnvironment(
107+
{
108+
NODE_ENV: "production",
109+
},
110+
"preview-deploy.vercel.app",
111+
),
112+
).toBe(false);
95113
});
96114

97115
it("returns false without analytics consent", () => {

src/lib/analytics/trackEvent.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ type AppEnvironment = {
252252
ANALYTICS_DEBUG?: string;
253253
};
254254

255+
const ANALYTICS_PRODUCTION_HOSTNAMES = new Set([
256+
"fusion.nuzlocke.io",
257+
"www.fusion.nuzlocke.io",
258+
]);
259+
255260
const createByEventCounter = (): Record<AnalyticsEventName, EventCounter> => {
256261
return {
257262
playthrough_created: { sent: 0, blocked: 0 },
@@ -386,11 +391,32 @@ function isValidEventPayload<EventName extends AnalyticsEventName>(
386391

387392
export function isAnalyticsProductionEnvironment(
388393
environment: AppEnvironment = process.env,
394+
browserHostname?: string,
389395
): boolean {
390-
return (
391-
environment.NODE_ENV === "production" &&
392-
environment.NEXT_PUBLIC_VERCEL_ENV === "production"
393-
);
396+
if (environment.NODE_ENV !== "production") {
397+
return false;
398+
}
399+
400+
if (environment.NEXT_PUBLIC_VERCEL_ENV === "production") {
401+
return true;
402+
}
403+
404+
if (
405+
environment.NEXT_PUBLIC_VERCEL_ENV === "preview" ||
406+
environment.NEXT_PUBLIC_VERCEL_ENV === "development"
407+
) {
408+
return false;
409+
}
410+
411+
const hostname =
412+
browserHostname ??
413+
(typeof window === "undefined" ? undefined : globalThis.location?.hostname);
414+
415+
if (hostname == null) {
416+
return false;
417+
}
418+
419+
return ANALYTICS_PRODUCTION_HOSTNAMES.has(hostname.toLowerCase());
394420
}
395421

396422
function getBrowserStorage(): Pick<Storage, "getItem"> | null {

0 commit comments

Comments
 (0)