Skip to content

Commit 5c5fe74

Browse files
authored
Merge pull request #896 from JoyAdah/fix/strip-referrer-tracking-headers-848
fix: strip referrer and tracking headers from gift card links
2 parents b9fc751 + 8cbbdc3 commit 5c5fe74

3 files changed

Lines changed: 74 additions & 3 deletions

File tree

client/lib/atomic-wallet.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
getAtomicWalletGiftCardLink,
66
normalizeGiftCardProvider,
77
getGiftCardProviderFromSubscription,
8+
stripTrackingParams,
89
} from "./atomic-wallet"
910

1011
describe("Atomic Wallet gift card deep links", () => {
@@ -44,3 +45,39 @@ describe("Atomic Wallet gift card deep links", () => {
4445
)
4546
})
4647
})
48+
49+
describe("stripTrackingParams", () => {
50+
it("strips UTM parameters from URLs", () => {
51+
const url = "https://example.com/page?amount=25&utm_source=app&utm_medium=referral&utm_campaign=test"
52+
const stripped = stripTrackingParams(url)
53+
expect(stripped).toBe("https://example.com/page?amount=25")
54+
})
55+
56+
it("strips fbclid and gclid parameters", () => {
57+
const url = "https://example.com/?item=1&fbclid=abc123&gclid=def456"
58+
const stripped = stripTrackingParams(url)
59+
expect(stripped).toBe("https://example.com/?item=1")
60+
})
61+
62+
it("strips ref and source parameters", () => {
63+
const url = "https://example.com/?amount=10&ref=syncro&source=app"
64+
const stripped = stripTrackingParams(url)
65+
expect(stripped).toBe("https://example.com/?amount=10")
66+
})
67+
68+
it("preserves non-tracking parameters", () => {
69+
const url = "https://example.com/buy?amount=25&provider=amazon"
70+
const stripped = stripTrackingParams(url)
71+
expect(stripped).toBe("https://example.com/buy?amount=25&provider=amazon")
72+
})
73+
74+
it("returns original string for non-URL inputs", () => {
75+
const url = "not-a-url"
76+
expect(stripTrackingParams(url)).toBe("not-a-url")
77+
})
78+
79+
it("handles URLs with no query params", () => {
80+
const url = "https://example.com/page"
81+
expect(stripTrackingParams(url)).toBe("https://example.com/page")
82+
})
83+
})

client/lib/atomic-wallet.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export const ATOMIC_WALLET_MOBILE_SCHEME = "atomicwallet://buy-gift-card"
22
export const ATOMIC_WALLET_WEB_URL = "https://atomicwallet.io/buy-gift-cards"
33

4+
const TRACKING_PARAM_PREFIXES = ["utm_", "fbclid", "gclid", "ref", "source", "campaign", "medium", "content", "term"]
5+
46
const GIFT_CARD_PROVIDER_ALIASES: Array<[RegExp, string]> = [
57
[/amazon/i, "amazon"],
68
[/google\s*play|youtube|google play/i, "google_play"],
@@ -14,6 +16,25 @@ const SUPPORTED_GIFT_CARD_PROVIDERS = new Set(
1416
GIFT_CARD_PROVIDER_ALIASES.map(([, provider]) => provider),
1517
)
1618

19+
export function stripTrackingParams(url: string): string {
20+
try {
21+
const parsed = new URL(url)
22+
const keysToRemove: string[] = []
23+
parsed.searchParams.forEach((_, key) => {
24+
const lower = key.toLowerCase()
25+
if (TRACKING_PARAM_PREFIXES.some((prefix) => lower.startsWith(prefix))) {
26+
keysToRemove.push(key)
27+
}
28+
})
29+
for (const key of keysToRemove) {
30+
parsed.searchParams.delete(key)
31+
}
32+
return parsed.toString()
33+
} catch {
34+
return url
35+
}
36+
}
37+
1738
export function normalizeGiftCardProvider(provider: string): string {
1839
return provider.trim().replace(/\s+/g, "_").toLowerCase()
1940
}
@@ -33,14 +54,18 @@ export function getAtomicWalletGiftCardDeepLink(amount: number, provider: string
3354
const normalizedProvider = normalizeGiftCardProvider(provider)
3455
const encodedProvider = encodeURIComponent(normalizedProvider)
3556
const encodedAmount = encodeURIComponent(amount.toString())
36-
return `${ATOMIC_WALLET_MOBILE_SCHEME}?amount=${encodedAmount}&provider=${encodedProvider}`
57+
return stripTrackingParams(
58+
`${ATOMIC_WALLET_MOBILE_SCHEME}?amount=${encodedAmount}&provider=${encodedProvider}`
59+
)
3760
}
3861

3962
export function getAtomicWalletGiftCardWebLink(amount: number, provider: string): string {
4063
const normalizedProvider = normalizeGiftCardProvider(provider)
4164
const encodedProvider = encodeURIComponent(normalizedProvider)
4265
const encodedAmount = encodeURIComponent(amount.toString())
43-
return `${ATOMIC_WALLET_WEB_URL}?amount=${encodedAmount}&provider=${encodedProvider}`
66+
return stripTrackingParams(
67+
`${ATOMIC_WALLET_WEB_URL}?amount=${encodedAmount}&provider=${encodedProvider}`
68+
)
4469
}
4570

4671
export function getAtomicWalletGiftCardLink(amount: number, provider: string): string {
@@ -59,7 +84,7 @@ export function openAtomicWalletGiftCard(amount: number, provider: string): stri
5984
const url = getAtomicWalletGiftCardLink(amount, provider)
6085

6186
if (typeof window !== "undefined") {
62-
window.location.href = url
87+
window.open(url, "_blank", "noreferrer,noopener")
6388
}
6489

6590
return url

client/next.config.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ const nextConfig = {
2020
},
2121
async headers() {
2222
return [
23+
{
24+
source: '/:path*',
25+
headers: [
26+
{
27+
key: 'Referrer-Policy',
28+
value: 'no-referrer',
29+
},
30+
],
31+
},
2332
{
2433
source: '/sw.js',
2534
headers: [

0 commit comments

Comments
 (0)