Support more utm tracking

This commit is contained in:
Seth Call 2026-01-23 23:17:35 -06:00
parent f1992eaa78
commit e82450dfe9
5 changed files with 139 additions and 18 deletions

View File

@ -32,7 +32,14 @@ ActiveAdmin.register_page "Jammers Subscription Cohorts" do
filter_type = params[:filter_type] || 'All' filter_type = params[:filter_type] || 'All'
filter_campaign = params[:filter_campaign] filter_campaign = params[:filter_campaign]
filter_campaign_id = params[:filter_campaign_id]
filter_ad_set = params[:filter_ad_set]
filter_ad_name = params[:filter_ad_name]
campaigns = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_utm_campaign).compact.sort campaigns = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_utm_campaign).compact.sort
campaign_ids = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_id).compact.sort
ad_sets = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_term).compact.sort
ad_names = User.where("origin_utm_source ILIKE '%meta%'").distinct.pluck(:origin_content).compact.sort
div style: "margin-bottom: 20px; padding: 10px; background-color: #f4f4f4; border-radius: 4px;" do div style: "margin-bottom: 20px; padding: 10px; background-color: #f4f4f4; border-radius: 4px;" do
form action: admin_jammers_subscription_cohorts_path, method: :get do form action: admin_jammers_subscription_cohorts_path, method: :get do
@ -44,11 +51,43 @@ ActiveAdmin.register_page "Jammers Subscription Cohorts" do
end end
if filter_type == 'Advertising' if filter_type == 'Advertising'
span "Campaign: ", style: "font-weight: bold; margin-right: 5px;" div style: "margin-top: 10px;" do
select name: 'filter_campaign', onchange: 'this.form.submit()', style: "margin-right: 15px;" do span "Campaign Name: ", style: "font-weight: bold; margin-right: 5px;"
option "All Campaigns", value: '' select name: 'filter_campaign', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
campaigns.each do |c| option "All", value: ''
option c, value: c, selected: filter_campaign == c option "Null", value: 'NULL', selected: filter_campaign == 'NULL'
campaigns.each do |c|
option c, value: c, selected: filter_campaign == c
end
end
span "Campaign ID: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_campaign_id', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_campaign_id == 'NULL'
campaign_ids.each do |c|
option c, value: c, selected: filter_campaign_id == c
end
end
end
div style: "margin-top: 10px;" do
span "Ad Set: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_ad_set', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_ad_set == 'NULL'
ad_sets.each do |c|
option c, value: c, selected: filter_ad_set == c
end
end
span "Ad Name: ", style: "font-weight: bold; margin-right: 5px;"
select name: 'filter_ad_name', onchange: 'this.form.submit()', style: "margin-right: 15px;" do
option "All", value: ''
option "Null", value: 'NULL', selected: filter_ad_name == 'NULL'
ad_names.each do |c|
option c, value: c, selected: filter_ad_name == c
end
end end
end end
end end
@ -87,8 +126,37 @@ ActiveAdmin.register_page "Jammers Subscription Cohorts" do
query = query.where("users.origin_utm_source = 'organic'") query = query.where("users.origin_utm_source = 'organic'")
elsif filter_type == 'Advertising' elsif filter_type == 'Advertising'
query = query.where("users.origin_utm_source ILIKE '%meta%'") query = query.where("users.origin_utm_source ILIKE '%meta%'")
if filter_campaign.present? if filter_campaign.present?
query = query.where("users.origin_utm_campaign = ?", filter_campaign) if filter_campaign == 'NULL'
query = query.where("users.origin_utm_campaign IS NULL")
else
query = query.where("users.origin_utm_campaign = ?", filter_campaign)
end
end
if filter_campaign_id.present?
if filter_campaign_id == 'NULL'
query = query.where("users.origin_id IS NULL")
else
query = query.where("users.origin_id = ?", filter_campaign_id)
end
end
if filter_ad_set.present?
if filter_ad_set == 'NULL'
query = query.where("users.origin_term IS NULL")
else
query = query.where("users.origin_term = ?", filter_ad_set)
end
end
if filter_ad_name.present?
if filter_ad_name == 'NULL'
query = query.where("users.origin_content IS NULL")
else
query = query.where("users.origin_content = ?", filter_ad_name)
end
end end
end end

View File

@ -32,11 +32,18 @@ const MetaTracking = {
}, },
handleUtm: function (searchParams) { handleUtm: function (searchParams) {
const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; if (!searchParams) return;
utmParams.forEach(param => {
const value = this.getQueryParam(param, searchParams); const query = searchParams.substring(1);
if (value) { const vars = query.split('&');
this.setCookie(param, value, 90); vars.forEach(v => {
const pair = v.split('=');
if (pair.length === 2) {
const key = decodeURIComponent(pair[0]);
const value = decodeURIComponent(pair[1]);
if (key.indexOf('utm_') === 0) {
this.setCookie(key, value, 90);
}
} }
}); });
}, },

View File

@ -0,0 +1,31 @@
class AddExtendedUtmToUsers < ActiveRecord::Migration[5.0]
def up
execute <<-SQL
ALTER TABLE users ADD COLUMN origin_id character varying;
ALTER TABLE users ADD COLUMN origin_term character varying;
ALTER TABLE users ADD COLUMN origin_content character varying;
CREATE INDEX index_users_on_origin_id ON users (origin_id);
CREATE INDEX index_users_on_origin_term ON users (origin_term);
CREATE INDEX index_users_on_origin_content ON users (origin_content);
CREATE INDEX index_users_on_origin_utm_source ON users (origin_utm_source);
CREATE INDEX index_users_on_origin_utm_medium ON users (origin_utm_medium);
SQL
end
def down
execute <<-SQL
DROP INDEX IF EXISTS index_users_on_origin_utm_medium;
DROP INDEX IF EXISTS index_users_on_origin_utm_source;
DROP INDEX IF EXISTS index_users_on_origin_content;
DROP INDEX IF EXISTS index_users_on_origin_term;
DROP INDEX IF EXISTS index_users_on_origin_id;
ALTER TABLE users DROP COLUMN IF EXISTS origin_content;
ALTER TABLE users DROP COLUMN IF EXISTS origin_term;
ALTER TABLE users DROP COLUMN IF EXISTS origin_id;
SQL
end
end

View File

@ -1664,11 +1664,17 @@ module JamRuby
user.origin_utm_source = origin["utm_source"] user.origin_utm_source = origin["utm_source"]
user.origin_utm_medium = origin["utm_medium"] user.origin_utm_medium = origin["utm_medium"]
user.origin_utm_campaign = origin["utm_campaign"] user.origin_utm_campaign = origin["utm_campaign"]
user.origin_id = origin["utm_id"]
user.origin_term = origin["utm_term"]
user.origin_content = origin["utm_content"]
user.origin_referrer = origin["referrer"] user.origin_referrer = origin["referrer"]
else else
user.origin_utm_source = 'organic' user.origin_utm_source = 'organic'
user.origin_utm_medium = 'organic' user.origin_utm_medium = 'organic'
user.origin_utm_campaign = nil user.origin_utm_campaign = nil
user.origin_id = nil
user.origin_term = nil
user.origin_content = nil
user.origin_referrer = nil user.origin_referrer = nil
end end

View File

@ -35,14 +35,23 @@
}, },
handleUtm: function (searchParams) { handleUtm: function (searchParams) {
var utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
var self = this; var self = this;
// forEach not supported in IE8, but this is modern enough or we can use for loop if (!searchParams) return;
for (var i = 0; i < utmParams.length; i++) {
var param = utmParams[i]; // Logically, we want to capture all utm_ parameters.
var value = self.getQueryParam(param, searchParams); // We can either iterate a list or dynamic regex.
if (value) { // Given the requirement to be robust, let's look for "utm_"
self.setCookie(param, value, 90);
var query = searchParams.substring(1); // remove '?'
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (pair.length === 2) {
var key = decodeURIComponent(pair[0]);
var value = decodeURIComponent(pair[1]);
if (key.indexOf('utm_') === 0) {
self.setCookie(key, value, 90);
}
} }
} }
}, },