Skip to content

Instantly share code, notes, and snippets.

@joostvanhoof
Last active September 6, 2023 00:16
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joostvanhoof/c8a4c46f14ae1c0a04cb1df8649feb7b to your computer and use it in GitHub Desktop.
Save joostvanhoof/c8a4c46f14ae1c0a04cb1df8649feb7b to your computer and use it in GitHub Desktop.
Feather Attribution script
// www.featherattribution.com. Brought to you by www.scrapingbee.com and www.freddyfeedback.com
class FeatherAttribution {
constructor(options) {
this.storageItems = ['feather_utm_source', 'feather_utm_medium', 'feather_utm_campaign', 'feather_utm_content', 'feather_ref', 'feather_referrer'];
this.checkExpiryDates();
this.setOptions(options);
this.referrer = document.referrer;
this.ref = this.getParameterByName('ref');
this.utm_source = this.getParameterByName('utm_source');
this.utm_medium = this.getParameterByName('utm_medium');
this.utm_campaign = this.getParameterByName('utm_campaign');
this.utm_content = this.getParameterByName('utm_content');
this.setAllLocalStorageItems();
}
checkExpiryDates() {
this.storageItems.forEach(element => {
const item = localStorage.getItem(element);
const now = new Date();
if(item) {
const itemDetails = JSON.parse(item);
if (now.getTime() > itemDetails.expiry) {
localStorage.removeItem(element);
}
}
});
}
setOptions(options) {
if (typeof options !== "undefined") {
options.hasOwnProperty('expires_in_days') ? this.expires_in_days = options.expires_in_days : 30;
options.hasOwnProperty('attribution_type_utm') ? this.attribution_type_utm = options.attribution_type_utm : 'first';
options.hasOwnProperty('attribution_type_ref') ? this.attribution_type_ref = options.attribution_type_ref : 'first';
options.hasOwnProperty('attribution_type_referrer') ? this.attribution_type_referrer = options.attribution_type_referrer : 'last';
} else {
this.expires_in_days = 30;
this.attribution_type_utm = 'first';
this.attribution_type_ref = 'first';
this.attribution_type_referrer = 'last';
}
const now = new Date();
this.expires_on = now.getTime() + (86400000 * this.expires_in_days);
}
getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
var results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
truncateString(string) {
if (string.length < 255) {
return string;
}
return string.substring(0, 255);
}
setLocalStorage(key, value, attribution_type) {
if(!value) {
return;
}
const item = {
value: this.truncateString(value),
expiry: this.expires_on,
}
if(attribution_type == 'last') {
localStorage.removeItem(key);
localStorage.setItem(key, JSON.stringify(item));
}
if(attribution_type == 'first' && this.getLocalStorage(key) == null) {
localStorage.setItem(key, JSON.stringify(item));
}
}
getLocalStorage(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) {
return null;
}
const item = JSON.parse(itemStr);
return item.value;
}
setAllLocalStorageItems() {
this.setLocalStorage('feather_utm_source', this.utm_source, this.attribution_type_utm);
this.setLocalStorage('feather_utm_medium', this.utm_medium, this.attribution_type_utm);
this.setLocalStorage('feather_utm_campaign', this.utm_campaign, this.attribution_type_utm);
this.setLocalStorage('feather_utm_content', this.utm_content, this.attribution_type_utm);
this.setLocalStorage('feather_ref', this.ref, this.attribution_type_ref);
this.setLocalStorage('feather_referrer', this.referrer, this.attribution_type_referrer);
}
fillFieldsWithValues() {
this.fillSingleFieldWithValue('utm_source', 'feather_utm_source');
this.fillSingleFieldWithValue('utm_medium', 'feather_utm_medium');
this.fillSingleFieldWithValue('utm_campaign', 'feather_utm_campaign');
this.fillSingleFieldWithValue('utm_content', 'feather_utm_content');
this.fillSingleFieldWithValue('ref', 'feather_ref');
this.fillSingleFieldWithValue('referrer', 'feather_referrer');
}
fillSingleFieldWithValue(field, value) {
if(document.getElementById(field)) {
document.getElementById(field).value = this.getLocalStorage(value);
} else {
console.warn('Can not find the field with id = ' + field);
}
}
}
window.featherAttribution = new FeatherAttribution({
expires_in_days: 30,
attribution_type_utm: 'first',
attribution_type_ref: 'first',
attribution_type_referrer: 'last'
});
@johnhearfield
Copy link

Would you consider the idea of automatically adding the hidden input fields to every form on the page if the UTM parameters are detected? This plugin does that and a few more: https://github.com/medius/utm_form

@joostvanhoof
Copy link
Author

This script will not be under active development as it was a (very small) side project. Feel free to copy paste the snippet and change it as you like!

If fields are auto-added I’d do it by a class selector on the form. This way you can specify for each form whether you want to the forms auto-added. A second option would be to give the script an extra option parameter to set whether auto-adding is on or off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment