Last active
April 4, 2023 18:46
-
-
Save chillu/0f54097117094d9ad7247727b5e4a9cd to your computer and use it in GitHub Desktop.
UTM Runn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script type="text/javascript" src="/script.js"></script> | |
</head> | |
<body> | |
<p>Internal nav</p> | |
<ul> | |
<li><a href="/index.html">Home without UTM</a></li> | |
<li><a href="/blog/my-blog-post.html">Blog post without UTM</a></li> | |
<li><a href="/other-page.html">Other page without UTM</a></li> | |
<li><a href="/index.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Home with UTM</a></li> | |
<li><a href="/blog/my-blog-post.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Blog post with UTM</a></li> | |
<li><a href="/other-page.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Other page with UTM</a></li> | |
</ul> | |
<p>Test links</p> | |
<ul> | |
<li><a href="https://app.runn.io/users/sign_up?utm_source=my-link-source&utm_campaign=my-link-campaign">App signup link with UTM</a></li> | |
<li><a href="https://app.runn.io/users/sign_up">App signup link without UTM</a></li> | |
<li><a href="https://app.runn.io/users/login">App login link</a></li> | |
<li><a href="/internal-link-utm?utm_source=my-link-source&utm_campaign=my-link-campaign">Internal link with UTM</a></li> | |
<li><a href="/internal-link">Internal link without UTM</a></li> | |
<li><a href="https://my-link-source.com">External link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true">Link with unrelated param</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" class="ga-track" data-ga-category="bla">Custom GA event link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" data-plausible-goal="Custom goal" data-ga-category="bla">Custom Plausible goal link</a></li> | |
</ul> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script type="text/javascript" src="/script.js"></script> | |
</head> | |
<body> | |
<p>Internal nav</p> | |
<ul> | |
<li><a href="/index.html">Home without UTM</a></li> | |
<li><a href="/blog/my-blog-post.html">Blog post without UTM</a></li> | |
<li><a href="/other-page.html">Other page without UTM</a></li> | |
<li><a href="/index.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Home with UTM</a></li> | |
<li><a href="/blog/my-blog-post.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Blog post with UTM</a></li> | |
<li><a href="/other-page.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Other page with UTM</a></li> | |
</ul> | |
<p>Test links</p> | |
<ul> | |
<li><a href="https://app.runn.io/users/sign_up?utm_source=my-link-source&utm_campaign=my-link-campaign">App signup link with UTM</a></li> | |
<li><a href="https://app.runn.io/users/sign_up">App signup link without UTM</a></li> | |
<li><a href="https://app.runn.io/users/login">App login link</a></li> | |
<li><a href="/internal-link-utm?utm_source=my-link-source&utm_campaign=my-link-campaign">Internal link with UTM</a></li> | |
<li><a href="/internal-link">Internal link without UTM</a></li> | |
<li><a href="https://my-link-source.com">External link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true">Link with unrelated param</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" class="ga-track" data-ga-category="bla">Custom GA event link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" data-plausible-goal="Custom goal" data-ga-category="bla">Custom Plausible goal link</a></li> | |
</ul> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script type="text/javascript" src="/script.js"></script> | |
</head> | |
<body> | |
<p>Internal nav</p> | |
<ul> | |
<li><a href="/index.html">Home without UTM</a></li> | |
<li><a href="/blog/my-blog-post.html">Blog post without UTM</a></li> | |
<li><a href="/other-page.html">Other page without UTM</a></li> | |
<li><a href="/index.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Home with UTM</a></li> | |
<li><a href="/blog/my-blog-post.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Blog post with UTM</a></li> | |
<li><a href="/other-page.html?utm_source=existing&utm_content=existing&utm_medium=existing&utm_campaign=existing">Other page with UTM</a></li> | |
</ul> | |
<p>Test links</p> | |
<ul> | |
<li><a href="https://app.runn.io/users/sign_up?utm_source=my-link-source&utm_campaign=my-link-campaign">App signup link with UTM</a></li> | |
<li><a href="https://app.runn.io/users/sign_up">App signup link without UTM</a></li> | |
<li><a href="https://app.runn.io/users/login">App login link</a></li> | |
<li><a href="/internal-link-utm?utm_source=my-link-source&utm_campaign=my-link-campaign">Internal link with UTM</a></li> | |
<li><a href="/internal-link">Internal link without UTM</a></li> | |
<li><a href="https://my-link-source.com">External link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true">Link with unrelated param</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" class="ga-track" data-ga-category="bla">Custom GA event link</a></li> | |
<li><a href="relative-link-unrelated-param/?unrelated_param=true" data-plausible-goal="Custom goal" data-ga-category="bla">Custom Plausible goal link</a></li> | |
</ul> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const LS_KEY = 'runnUtmParams'; | |
const ADD_TRACKING_LINKS_REGEX = /app.runn.io\/users\/sign_up/; | |
const DEFAULT_SOURCE = 'runn.io'; | |
function paramFilter(params, re) { | |
let filtered = {} | |
params.forEach((value, key) => { | |
if (key.match(re)) { | |
filtered[key] = value; | |
} | |
}) | |
return filtered; | |
} | |
function addNewParams(href, params) { | |
const urlObj = new URL(href); | |
Object.keys(params).forEach(param => { | |
// Don't overwrite | |
if (urlObj.searchParams.get(param)) return; | |
urlObj.searchParams.set(param, params[param]); | |
}) | |
return urlObj.toString(); | |
} | |
function storeTracking(currentHref) { | |
const ls = window.localStorage; | |
if (!ls) { | |
return | |
} | |
// Only store the first time a visitor arrives. | |
// This ensures the "landing page" is tracked. | |
if (ls.getItem(LS_KEY)) { | |
return | |
} | |
const currentUrl = new URL(currentHref); | |
let utmParams = paramFilter(currentUrl.searchParams, /^utm/); | |
// Track landing page on first visit to provide more attribution context. | |
// Only do this when no UTM is present, to avoid mixing UTM data from different contextx. | |
if (currentUrl.pathname.match(/^\/blog/) && !Object.keys(utmParams).length) { | |
const source = document.referrer ? (new URL(document.referrer)).hostname : null; | |
utmParams = { | |
utm_medium: 'blog', | |
utm_campaign: 'organic', | |
utm_source: source ? source : DEFAULT_SOURCE, | |
utm_content: currentUrl.pathname, | |
} | |
} | |
ls.setItem(LS_KEY, JSON.stringify(utmParams)); | |
} | |
// Ensure UTM tracking survives internal navigation without requiring explicit UTM | |
// on certain outgoing links, and allows more granular attribution. | |
// This is a workaround for not having continuous tracking tooling on sessions between | |
// the website and app (for privacy and regulatory reasons). | |
function addTrackingToAppLinks(currentHref) { | |
const currentUrl = new URL(currentHref); | |
const utmParams = window.localStorage ? JSON.parse(window.localStorage.getItem(LS_KEY)) : null; | |
if (!utmParams) { | |
return; | |
} | |
Array.from(document.getElementsByTagName('a')).forEach(el => { | |
if(!el.href || !el.href.match(ADD_TRACKING_LINKS_REGEX)) { | |
return; | |
} | |
// Add new params *without* overwriting existing ones on the link | |
el.href = addNewParams(el.href, utmParams); | |
}); | |
} | |
// Custom event tracking defined on link elements | |
function addEventTrackingToLinks() { | |
Array.from(document.getElementsByClassName('ga-track')).forEach(el => { | |
el.addEventListener('click', () => { | |
// Plausible tracking | |
if (typeof plausible !== 'undefined') { | |
plausible(el.dataset.plausibleGoal ? el.dataset.plausibleGoal : 'Signup'); | |
} | |
// Google Analytics tracking | |
if (typeof window.ga !== 'undefined') { | |
const gaEvent = { | |
hitType: 'event', | |
eventAction: 'click', | |
eventCategory: 'unknown', | |
transport: 'beacon', | |
} | |
if (el.dataset.gaCategory) { gaEvent.eventCategory = el.dataset.gaCategory } | |
if (el.dataset.gaAction) { gaEvent.eventAction = el.dataset.gaAction } | |
if (el.dataset.gaLabel) { gaEvent.eventLabel = el.dataset.gaLabel } | |
window.ga('send', 'event', gaEvent); | |
} | |
}); | |
}) | |
} | |
window.addEventListener('DOMContentLoaded', (event) => { | |
storeTracking(document.location.href) | |
addTrackingToAppLinks(document.location.href) | |
addEventTrackingToLinks() | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment