68 lines
2.1 KiB
JavaScript
68 lines
2.1 KiB
JavaScript
/**
|
|
* utm.js — trackable campaign links (spec §7 `utm_links` entity).
|
|
*
|
|
* Mints a UTM-tagged URL to the public landing page so every ad click is attributable
|
|
* end-to-end (source / medium / campaign / content / term → destination). Front-end
|
|
* demo: pure string building, no shortener or backend.
|
|
*/
|
|
|
|
// Use the running app's origin so the copied link opens the demo landing page; in a
|
|
// real deployment this resolves to your public site (swap to your domain when hosting).
|
|
const ORIGIN = (typeof window !== 'undefined' && window.location?.origin) || 'https://lynkeduppro.com';
|
|
const BASE = `${ORIGIN}/ads/lp`;
|
|
|
|
// Ad medium by platform (search vs paid social vs messaging).
|
|
const MEDIUM = {
|
|
google: 'paid_search',
|
|
meta: 'paid_social',
|
|
linkedin: 'paid_social',
|
|
reddit: 'paid_social',
|
|
nextdoor: 'paid_social',
|
|
whatsapp: 'messaging',
|
|
};
|
|
|
|
const slug = (s) => (s || '')
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '')
|
|
.slice(0, 60);
|
|
|
|
/**
|
|
* Build the tracked link + its utm_links field breakdown for a campaign.
|
|
* Returns { url, fields }.
|
|
*/
|
|
export function buildUtm(campaign, { creative } = {}) {
|
|
const source = campaign.platform;
|
|
const medium = MEDIUM[source] || 'paid';
|
|
const name = slug(campaign.name) || campaign.blueprintId || 'campaign';
|
|
const content = creative ? (slug(creative.headline) || creative.id) : (campaign.creativeId || 'default');
|
|
const term = campaign.serviceType || '';
|
|
|
|
const params = {
|
|
c: campaign.blueprintId,
|
|
src: source,
|
|
utm_source: source,
|
|
utm_medium: medium,
|
|
utm_campaign: name,
|
|
utm_content: content,
|
|
utm_term: term,
|
|
};
|
|
const qs = Object.entries(params)
|
|
.filter(([, v]) => v)
|
|
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
|
|
.join('&');
|
|
|
|
return {
|
|
url: `${BASE}?${qs}`,
|
|
fields: {
|
|
campaignId: campaign.id || null,
|
|
source,
|
|
medium,
|
|
campaign: name,
|
|
content,
|
|
term,
|
|
destinationUrl: BASE,
|
|
},
|
|
};
|
|
}
|