@growth-labs/mailer 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/tracking-update.d.ts +21 -0
- package/dist/_internal/tracking-update.d.ts.map +1 -0
- package/dist/_internal/tracking-update.js +44 -0
- package/dist/_internal/tracking-update.js.map +1 -0
- package/dist/queue/consumer.d.ts.map +1 -1
- package/dist/queue/consumer.js +8 -2
- package/dist/queue/consumer.js.map +1 -1
- package/dist/routes/track-click.d.ts.map +1 -1
- package/dist/routes/track-click.js +20 -12
- package/dist/routes/track-click.js.map +1 -1
- package/dist/routes/track-open.d.ts.map +1 -1
- package/dist/routes/track-open.js +20 -12
- package/dist/routes/track-open.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/broadcast.d.ts.map +1 -1
- package/dist/utils/broadcast.js +5 -3
- package/dist/utils/broadcast.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/providers.d.ts.map +1 -1
- package/dist/utils/providers.js +92 -2
- package/dist/utils/providers.js.map +1 -1
- package/dist/utils/send.d.ts.map +1 -1
- package/dist/utils/send.js +3 -0
- package/dist/utils/send.js.map +1 -1
- package/dist/utils/utm.d.ts +26 -0
- package/dist/utils/utm.d.ts.map +1 -0
- package/dist/utils/utm.js +63 -0
- package/dist/utils/utm.js.map +1 -0
- package/package.json +1 -1
- package/src/_internal/tracking-update.ts +67 -0
- package/src/queue/consumer.ts +12 -2
- package/src/routes/track-click.ts +20 -12
- package/src/routes/track-open.ts +20 -12
- package/src/types.ts +2 -0
- package/src/utils/broadcast.ts +9 -3
- package/src/utils/index.ts +1 -0
- package/src/utils/providers.ts +86 -2
- package/src/utils/send.ts +3 -0
- package/src/utils/utm.ts +73 -0
package/src/utils/utm.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// UTM tagging for links in campaign, digest and broadcast emails.
|
|
2
|
+
//
|
|
3
|
+
// Mailer links used to reach GA4 untagged, so email clicks landed as direct
|
|
4
|
+
// traffic. Tagging happens before the click-tracking rewrite wraps each href,
|
|
5
|
+
// so the tagged URL is what the redirect finally sends the reader to.
|
|
6
|
+
|
|
7
|
+
/** UTM tags for links that stay on the sending site. */
|
|
8
|
+
export interface LinkUtm {
|
|
9
|
+
/** Sending site's host (e.g. `fronts.co`). Only links to it, or a subdomain, are tagged. */
|
|
10
|
+
siteHost: string
|
|
11
|
+
source: string
|
|
12
|
+
medium: string
|
|
13
|
+
/** Campaign or template identifier; reduced to `[a-z0-9_-]`. */
|
|
14
|
+
campaign: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function utmValue(value: string): string {
|
|
18
|
+
return value
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
21
|
+
.replace(/^-+|-+$/g, '')
|
|
22
|
+
.slice(0, 100)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The tags every campaign, digest and broadcast link to the sending site
|
|
27
|
+
* carries: source `newsletter`, medium `email`, campaign = the campaign id.
|
|
28
|
+
* GA4 files source/medium `newsletter / email` under its Email channel.
|
|
29
|
+
*/
|
|
30
|
+
export function emailLinkUtm(options: { siteUrl: string }, campaignId: string): LinkUtm {
|
|
31
|
+
return {
|
|
32
|
+
siteHost: new URL(options.siteUrl).hostname,
|
|
33
|
+
source: 'newsletter',
|
|
34
|
+
medium: 'email',
|
|
35
|
+
campaign: campaignId,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Add utm_source / utm_medium / utm_campaign to a link that points at the
|
|
41
|
+
* sending site. Off-site links, non-http(s) links, links with a template
|
|
42
|
+
* placeholder, and links that already carry a utm_source are returned as-is.
|
|
43
|
+
*/
|
|
44
|
+
export function addUtmParams(href: string, utm: LinkUtm): string {
|
|
45
|
+
if (href.includes('{{')) return href
|
|
46
|
+
let url: URL
|
|
47
|
+
try {
|
|
48
|
+
url = new URL(href)
|
|
49
|
+
} catch {
|
|
50
|
+
return href
|
|
51
|
+
}
|
|
52
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') return href
|
|
53
|
+
const host = url.hostname.toLowerCase()
|
|
54
|
+
const site = utm.siteHost.toLowerCase()
|
|
55
|
+
if (host !== site && !host.endsWith(`.${site}`)) return href
|
|
56
|
+
if (url.searchParams.has('utm_source')) return href
|
|
57
|
+
url.searchParams.set('utm_source', utmValue(utm.source))
|
|
58
|
+
url.searchParams.set('utm_medium', utmValue(utm.medium))
|
|
59
|
+
const campaign = utmValue(utm.campaign)
|
|
60
|
+
if (campaign) url.searchParams.set('utm_campaign', campaign)
|
|
61
|
+
return url.toString()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Tag every `<a href="...">` in the HTML that addUtmParams accepts. */
|
|
65
|
+
export function tagLinksWithUtm(html: string, utm: LinkUtm): string {
|
|
66
|
+
return html.replace(
|
|
67
|
+
/<a\s([^>]*?)href\s*=\s*"([^"]*)"([^>]*?)>/gi,
|
|
68
|
+
(match, before: string, href: string, after: string) => {
|
|
69
|
+
const tagged = addUtmParams(href, utm)
|
|
70
|
+
return tagged === href ? match : `<a ${before}href="${tagged}"${after}>`
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
}
|