Skip to content

Commit 6513253

Browse files
authored
Updated parser logic (#519)
ref https://linear.app/ghost/issue/PROD-4/ Some of the logic was inappropriately lined up, so this cleans up what is handled by the package in Ghost and this package. This package can now accept the full object created by the frontend attribution script (url, source, medium).
1 parent b478bbb commit 6513253

File tree

6 files changed

+124
-586
lines changed

6 files changed

+124
-586
lines changed

packages/referrer-parser/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { ReferrerData, ParserOptions } from './lib/ReferrerParser';
66
*
77
* @param referrerUrl - URL of the referrer to parse
88
* @param options - Configuration options
9+
* @param referrerSource - Optional source to override URL parameters
10+
* @param referrerMedium - Optional medium to override URL parameters
911
* @returns Parsed referrer data with source, medium and URL
1012
*
1113
* @example
@@ -18,10 +20,19 @@ import type { ReferrerData, ParserOptions } from './lib/ReferrerParser';
1820
* const result = parse('https://example.com/blog?utm_source=newsletter', {
1921
* siteUrl: 'https://example.com'
2022
* });
23+
*
24+
* @example
25+
* // With explicit source and medium
26+
* const result = parse('https://example.com', {}, 'newsletter', 'email');
2127
*/
22-
function parse(referrerUrl: string, options: ParserOptions = {}): ReferrerData {
28+
function parse(
29+
referrerUrl: string,
30+
options: ParserOptions = {},
31+
referrerSource?: string,
32+
referrerMedium?: string
33+
): ReferrerData {
2334
const parser = new ReferrerParser(options);
24-
return parser.parse(referrerUrl);
35+
return parser.parse(referrerUrl, referrerSource, referrerMedium);
2536
}
2637

2738
export {

packages/referrer-parser/lib/ReferrerParser.ts

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,41 +52,14 @@ export class ReferrerParser {
5252
* Parse a referrer URL to get source, medium and hostname
5353
*
5454
* @param referrerUrlStr - URL of the referrer
55-
* @returns Parsed referrer data with source, medium and URL
55+
* @param referrerSource - Source of the referrer
56+
* @param referrerMedium - Medium of the referrer
57+
* @returns Parsed referrer data with source, medium and URL. Internal referrers return null values.
5658
*/
57-
parse(referrerUrlStr: string): ReferrerData {
58-
if (!referrerUrlStr) {
59-
return {
60-
referrerSource: 'Direct',
61-
referrerMedium: null,
62-
referrerUrl: null
63-
};
64-
}
65-
59+
parse(referrerUrlStr: string, referrerSource?: string, referrerMedium?: string): ReferrerData {
6660
const referrerUrl = this.getUrlFromStr(referrerUrlStr);
67-
if (!referrerUrl) {
68-
return {
69-
referrerSource: 'Direct',
70-
referrerMedium: null,
71-
referrerUrl: null
72-
};
73-
}
7461

75-
// Skip Stripe checkout URLs
76-
if (referrerUrl.hostname === 'checkout.stripe.com') {
77-
return {
78-
referrerSource: 'Direct',
79-
referrerMedium: null,
80-
referrerUrl: null
81-
};
82-
}
83-
84-
// Check for source/medium in query parameters
85-
const urlParams = new URLSearchParams(referrerUrl.search);
86-
const referrerSource = urlParams.get('utm_source') || urlParams.get('source') || null;
87-
const referrerMedium = urlParams.get('utm_medium') || urlParams.get('medium') || null;
88-
89-
// If referrer is Ghost Explore
62+
// Ghost-specific cases
9063
if (this.isGhostExploreRef({referrerUrl, referrerSource})) {
9164
return {
9265
referrerSource: 'Ghost Explore',
@@ -100,14 +73,14 @@ export class ReferrerParser {
10073
return {
10174
referrerSource: 'Ghost.org',
10275
referrerMedium: 'Ghost Network',
103-
referrerUrl: referrerUrl?.hostname
76+
referrerUrl: referrerUrl?.hostname ?? null
10477
};
10578
}
10679

10780
// Check for Ghost Newsletter
108-
if (this.isGhostNewsletter({referrerSource})) {
81+
if (referrerSource && this.isGhostNewsletter({referrerSource})) {
10982
return {
110-
referrerSource: referrerSource!.replace(/-newsletter$/, ' newsletter'),
83+
referrerSource: referrerSource.replace(/-/g, ' '),
11184
referrerMedium: 'Email',
11285
referrerUrl: referrerUrl?.hostname ?? null
11386
};
@@ -148,10 +121,10 @@ export class ReferrerParser {
148121
}
149122

150123
return {
151-
referrerSource: 'Direct',
124+
referrerSource: null,
152125
referrerMedium: null,
153126
referrerUrl: null
154-
};
127+
}
155128
}
156129

157130
/**
@@ -259,7 +232,6 @@ export class ReferrerParser {
259232
* @returns True if the referrer is from Ghost Explore
260233
*/
261234
isGhostExploreRef({referrerUrl, referrerSource}: {referrerUrl: URL | null, referrerSource?: string | null}): boolean {
262-
// Always check for ghost-explore source param
263235
if (referrerSource === 'ghost-explore') {
264236
return true;
265237
}
@@ -268,12 +240,14 @@ export class ReferrerParser {
268240
return false;
269241
}
270242

271-
// Check domain for explore.ghost.io and try.ghost.org/explore
272-
if (referrerUrl.hostname === 'explore.ghost.io') {
243+
if (referrerUrl?.hostname
244+
&& this.adminUrl?.hostname === referrerUrl?.hostname
245+
&& referrerUrl?.pathname?.startsWith(this.adminUrl?.pathname)
246+
) {
273247
return true;
274248
}
275249

276-
if (referrerUrl.hostname === 'try.ghost.org' && referrerUrl.pathname.startsWith('/explore')) {
250+
if (referrerUrl.hostname === 'ghost.org' && referrerUrl.pathname.startsWith('/explore')) {
277251
return true;
278252
}
279253

0 commit comments

Comments
 (0)