← All Articles

Sign up attribution for a Rails app

Khash SajadiKhash Sajadi
Sep 18th 14Updated Jun 8th 22
Ruby on Rails

“I know I waste half of my advertising dollars...I just wish I knew which half.” said Henry Procter.

Knowing where your site signups come from is a good way of knowing if you are spending your advertisement dollars on the right target, but how would you do that?

Google Analytics is the most common tool used by many for that. The problem is Google Analytics can become very complicated very quickly. More importantly linking a campaign with a single signup is something that should happen in the app during the signup process. This will mark each individual user with the campaign they came from.

Mark your campaigns

Started by Google Analytics, UTM parameters in URLs were created to link campaigns to visits, but they are not limited to Google Analytics and are supported by almost any visitor tracking utility out there.

To start with, make sure all the links coming to your website use UTM parameters. You can use Google Analytics URL Builder or just simply add utm_source and utm_campaign to the URL coming to your site. This will end up looking something like this:

http://www.mysite.com?utm_source=test&utm_campaign=promo

Capture the UTM into a cookie

Not every one who visits the site is going to signup immediately, but they might do that later, so we need a way to capture that.

To achieve that, we are going to capture the utm parameters into a cookie that expires in a month. That way if the visitor signs up for up to a month, we know where he came from.

In Rails, we can do that by a filter:

before_filter :capture_utm

private

def capture_utm
	unless cookies[:utm]
  	cookies[:utm] = { :value => utm.to_json, :max_age => "2592000" }
	end
end

def utm
	{
		:utm_source => params[:utm_source],
		:utm_campaign => params[:utm_campaign],
		:utm_medium => params[:utm_medium],
		:utm_term => params[:utm_term],
		:utm_content => params[:utm_content]
	}
end

Read the cookie before signup

Linking the utm parameters with the new user is easy. If you are using Devise to manage your users, you can customise the signup controller to capture the value:

class CustomRegistrationsController < Devise::RegistrationsController

	def create
		super

		begin
			utm = cookies[:utm]
			if utm
				resource.utm_params = utm
				resource.save
			end
		rescue => exc 
			Rails.logger.error "Error reading utm cookie due to #{exc}"
		end

Make sure you add this line to your routes.rb:

devise_for :users, :controllers => {:registrations => “custom_registrations” }

utm_params is a text field we added to the User class in a migration. This will store the JSON serialised version of the utm parameters in database next to each new signup.

You might want to avoid addin the values if they are empty (like when the signup came from no campaign) but I prefer having them there all the time to simplify reading and deserialising them during analysis.

What if you have multiple subdomains?

If you are like us, you don't only have 1 website. We have a blog (this one), help website. Also our main website www.cloud66.com is a separate app.

All of our apps are hosted on cloud66.com subdomains: blog.cloud66.com, help.cloud66.com and community.cloud66.com

This means we can use cookies that run across all of our websites. In Rails you can do this by adding domain to the cookies.

This will change the capture_utm method above to this one:

def capture_utm
	unless cookies[:utm]
  	cookies[:utm] = { :value => utm.to_json, :max_age => "2592000", :domain => ".mydomain.com" }
	end
end

Note the . before the domain name. Using this method the cookies will be sent to the main app (where the signup happens) regardless of where the first visit was.

How about CDN?

We also use AWS Cloudfront as a CDN for our main website. This speeds up requests and reduces load on our servers. We use custom origin servers for our Cloudfront but the default settings is not going to work with the solution above.

This is because Cloudfront CDN by default ignores query strings and doesn't forward cookies to the origin server. Solving this is simple!

Login to your AWS Cloudfront dashboard and select the Cloudfront distribution. Under Behaviors, you can select edit and change these two settings:

Forward Query Strings to yes and
Forward Cookies to all

Done!


Try Cloud 66 for Free, No credit card required