mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
Move UTM parameter tracking logic into a concern
This commit is contained in:
parent
6787273713
commit
8e35b8e09f
4 changed files with 218 additions and 25 deletions
|
|
@ -1 +1 @@
|
|||
0.34.0
|
||||
0.34.1
|
||||
|
|
|
|||
33
app/controllers/concerns/utm_trackable.rb
Normal file
33
app/controllers/concerns/utm_trackable.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
UTM_PARAMS = %w[utm_source utm_medium utm_campaign utm_term utm_content].freeze
|
||||
|
||||
def store_utm_params
|
||||
UTM_PARAMS.each do |param|
|
||||
session[param] = params[param] if params[param].present?
|
||||
end
|
||||
end
|
||||
|
||||
def assign_utm_params(record)
|
||||
utm_data = extract_utm_data_from_session
|
||||
|
||||
return unless utm_data.any?
|
||||
|
||||
record.update_columns(utm_data)
|
||||
clear_utm_session
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def extract_utm_data_from_session
|
||||
UTM_PARAMS.each_with_object({}) do |param, hash|
|
||||
hash[param] = session[param] if session[param].present?
|
||||
end
|
||||
end
|
||||
|
||||
def clear_utm_session
|
||||
UTM_PARAMS.each { |param| session.delete(param) }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Users::RegistrationsController < Devise::RegistrationsController
|
||||
include UtmTrackable
|
||||
|
||||
before_action :set_invitation, only: %i[new create]
|
||||
before_action :check_registration_allowed, only: %i[new create]
|
||||
before_action :store_utm_params, only: %i[new]
|
||||
before_action :store_utm_params, only: %i[new], unless: -> { DawarichSettings.self_hosted? }
|
||||
|
||||
def new
|
||||
build_resource({})
|
||||
|
|
@ -67,8 +69,8 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||
|
||||
def invitation_token
|
||||
@invitation_token ||= params[:invitation_token] ||
|
||||
params.dig(:user, :invitation_token) ||
|
||||
session[:invitation_token]
|
||||
params.dig(:user, :invitation_token) ||
|
||||
session[:invitation_token]
|
||||
end
|
||||
|
||||
def accept_invitation_for_user(user)
|
||||
|
|
@ -82,33 +84,16 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||
if service.call
|
||||
flash[:notice] = "Welcome to #{@invitation.family.name}! You're now part of the family."
|
||||
else
|
||||
flash[:alert] = "Account created successfully, but there was an issue accepting the invitation: #{service.error_message}"
|
||||
flash[:alert] =
|
||||
"Account created successfully, but there was an issue accepting the invitation: #{service.error_message}"
|
||||
end
|
||||
rescue StandardError => e
|
||||
Rails.logger.error "Error accepting invitation during registration: #{e.message}"
|
||||
flash[:alert] = "Account created successfully, but there was an issue accepting the invitation. Please try accepting it again."
|
||||
flash[:alert] =
|
||||
'Account created successfully, but there was an issue accepting the invitation. Please try accepting it again.'
|
||||
end
|
||||
|
||||
def sign_up_params
|
||||
super
|
||||
end
|
||||
|
||||
def store_utm_params
|
||||
utm_params = %w[utm_source utm_medium utm_campaign utm_term utm_content]
|
||||
utm_params.each do |param|
|
||||
session[param] = params[param] if params[param].present?
|
||||
end
|
||||
end
|
||||
|
||||
def assign_utm_params(user)
|
||||
utm_params = %w[utm_source utm_medium utm_campaign utm_term utm_content]
|
||||
utm_data = {}
|
||||
|
||||
utm_params.each do |param|
|
||||
utm_data[param] = session[param] if session[param].present?
|
||||
session.delete(param) # Clean up session after assignment
|
||||
end
|
||||
|
||||
user.update_columns(utm_data) if utm_data.any?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -325,4 +325,179 @@ RSpec.describe 'Users::Registrations', type: :request do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'UTM Parameter Tracking' do
|
||||
let(:utm_params) do
|
||||
{
|
||||
utm_source: 'google',
|
||||
utm_medium: 'cpc',
|
||||
utm_campaign: 'winter_2025',
|
||||
utm_term: 'location_tracking',
|
||||
utm_content: 'banner_ad'
|
||||
}
|
||||
end
|
||||
|
||||
context 'when self-hosted mode is disabled' do
|
||||
before do
|
||||
allow(DawarichSettings).to receive(:self_hosted?).and_return(false)
|
||||
end
|
||||
|
||||
it 'captures UTM parameters from registration page URL' do
|
||||
get new_user_registration_path, params: utm_params
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(session[:utm_source]).to eq('google')
|
||||
expect(session[:utm_medium]).to eq('cpc')
|
||||
expect(session[:utm_campaign]).to eq('winter_2025')
|
||||
expect(session[:utm_term]).to eq('location_tracking')
|
||||
expect(session[:utm_content]).to eq('banner_ad')
|
||||
end
|
||||
|
||||
it 'stores UTM parameters in user record after registration' do
|
||||
# Visit registration page with UTM params
|
||||
get new_user_registration_path, params: utm_params
|
||||
|
||||
# Create account
|
||||
unique_email = "utm-user-#{Time.current.to_i}@example.com"
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: unique_email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
}
|
||||
}
|
||||
|
||||
# Verify UTM params were saved to user
|
||||
user = User.find_by(email: unique_email)
|
||||
expect(user.utm_source).to eq('google')
|
||||
expect(user.utm_medium).to eq('cpc')
|
||||
expect(user.utm_campaign).to eq('winter_2025')
|
||||
expect(user.utm_term).to eq('location_tracking')
|
||||
expect(user.utm_content).to eq('banner_ad')
|
||||
end
|
||||
|
||||
it 'clears UTM parameters from session after registration' do
|
||||
# Visit registration page with UTM params
|
||||
get new_user_registration_path, params: utm_params
|
||||
|
||||
# Create account
|
||||
unique_email = "utm-cleanup-#{Time.current.to_i}@example.com"
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: unique_email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
}
|
||||
}
|
||||
|
||||
# Verify session was cleaned up
|
||||
expect(session[:utm_source]).to be_nil
|
||||
expect(session[:utm_medium]).to be_nil
|
||||
expect(session[:utm_campaign]).to be_nil
|
||||
expect(session[:utm_term]).to be_nil
|
||||
expect(session[:utm_content]).to be_nil
|
||||
end
|
||||
|
||||
it 'handles partial UTM parameters' do
|
||||
partial_utm = { utm_source: 'twitter', utm_campaign: 'spring_promo' }
|
||||
|
||||
get new_user_registration_path, params: partial_utm
|
||||
|
||||
unique_email = "partial-utm-#{Time.current.to_i}@example.com"
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: unique_email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
}
|
||||
}
|
||||
|
||||
user = User.find_by(email: unique_email)
|
||||
expect(user.utm_source).to eq('twitter')
|
||||
expect(user.utm_campaign).to eq('spring_promo')
|
||||
expect(user.utm_medium).to be_nil
|
||||
expect(user.utm_term).to be_nil
|
||||
expect(user.utm_content).to be_nil
|
||||
end
|
||||
|
||||
it 'does not store empty UTM parameters' do
|
||||
empty_utm = {
|
||||
utm_source: '',
|
||||
utm_medium: '',
|
||||
utm_campaign: 'campaign_only'
|
||||
}
|
||||
|
||||
get new_user_registration_path, params: empty_utm
|
||||
|
||||
unique_email = "empty-utm-#{Time.current.to_i}@example.com"
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: unique_email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
}
|
||||
}
|
||||
|
||||
user = User.find_by(email: unique_email)
|
||||
expect(user.utm_source).to be_nil
|
||||
expect(user.utm_medium).to be_nil
|
||||
expect(user.utm_campaign).to eq('campaign_only')
|
||||
end
|
||||
|
||||
it 'works with family invitations' do
|
||||
get new_user_registration_path, params: utm_params.merge(invitation_token: invitation.token)
|
||||
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: invitation.email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
},
|
||||
invitation_token: invitation.token
|
||||
}
|
||||
|
||||
user = User.find_by(email: invitation.email)
|
||||
expect(user.utm_source).to eq('google')
|
||||
expect(user.utm_campaign).to eq('winter_2025')
|
||||
expect(user.family).to eq(family)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when self-hosted mode is enabled' do
|
||||
before do
|
||||
allow(ENV).to receive(:[]).and_call_original
|
||||
allow(ENV).to receive(:[]).with('SELF_HOSTED').and_return('true')
|
||||
end
|
||||
|
||||
it 'does not capture UTM parameters' do
|
||||
# With valid invitation to allow registration in self-hosted mode
|
||||
get new_user_registration_path, params: utm_params.merge(invitation_token: invitation.token)
|
||||
|
||||
expect(session[:utm_source]).to be_nil
|
||||
expect(session[:utm_medium]).to be_nil
|
||||
expect(session[:utm_campaign]).to be_nil
|
||||
end
|
||||
|
||||
it 'does not store UTM parameters in user record' do
|
||||
# With valid invitation to allow registration in self-hosted mode
|
||||
get new_user_registration_path, params: utm_params.merge(invitation_token: invitation.token)
|
||||
|
||||
post user_registration_path, params: {
|
||||
user: {
|
||||
email: invitation.email,
|
||||
password: 'password123',
|
||||
password_confirmation: 'password123'
|
||||
},
|
||||
invitation_token: invitation.token
|
||||
}
|
||||
|
||||
user = User.find_by(email: invitation.email)
|
||||
expect(user.utm_source).to be_nil
|
||||
expect(user.utm_medium).to be_nil
|
||||
expect(user.utm_campaign).to be_nil
|
||||
expect(user.utm_term).to be_nil
|
||||
expect(user.utm_content).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue