Michael Trojanek (relativkreativ) — Bootstrapper and creator of things

This article was published on November 3rd 2015 and takes about 4 minutes to read.

Use it with caution — it is probably still valid, but it has not been updated for over a year.

How to set cookies across different top level domains

Setting cookies for a domain different from the one the visitor is currently on is actually not possible. Learn how to do it nonetheless.

Identifying existing customers is the key to improving your visitor's experience when visiting your websites — you would not want to prompt existing customers to join your email list or invite them to buy your latest product when they already did.

While it is quite easy to identify (and remember) an existing customer if you only run a single website, things get trickier if you have multiple websites. You cannot set cookies for a domain different from the one that is currently visited (we are not talking about subdomains here, but toplevel domains like domain1.com and domain2.com) — this is against a cookie's nature.

This does not mean that it is impossible, it just involves a little more work.

Let me show you how I do it:

Identifying an existing customer

For every visitor who joins my email list, I generate a unique token and store it in my main application's database (along some important information like when and where they joined). Let's call this token, well, token.

I append ?token=abc to every link to one of my websites I include in a message to my email list (where abc corresponds to each subscriber's personal token). How you manage that is up to you as it is dependent on the mail service provider you are using.

Once you have generated such a link, all you need to identify an existing customer is a before_action on every action of your application that could possibly be the target of such a link. You probably want to define it on ApplicationController and skip it with skip_before_action eventually:

class ApplicationController < ActionController::Base
  before_action :set_cookie


  def set_cookie
    cookies.signed.permanent[:token] = params[:token] if params[:token].present?

That's the easy part. When the requested URL includes a query string with a token, this token is written to a permanent signed cookie.

Now you can use another before_action to set a @current_customer variable for example.

In order to also set this cookie on another website, you have no other choice but to redirect the visitor back and forth.

A method similar to the following has to be called as before_action after the one that sets the cookie:

def spread_cookie
  return if params[:token].blank?

  redirect_to URI.decode(params[:origin]) and return if params[:origin].present?

  destination = case request.host.split(".")[-2]
                  when "domain1"
                  when "domain2"
  origin = URI.encode(request.original_url.split("?").first)

  redirect_to "#{destination}?token=#{params[:token]}&origin=#{origin}" and return

When the origin parameter is not set (which it is not initially), this method redirects to your other website (when visiting domain1.com, it redirects to domain2.com and vice versa) and appends an origin parameter which holds the original URL without its query string.

When the origin parameter is set (which it is on the website where the visitor is redirected to), the method redirects back to origin (the original URL without the query string), thus hiding the token form the browser's address bar.


Testing this stuff is quite tedious. I recommend you use pow to run your applications locally — this makes it a lot easier than with applications running on different ports of localhost.

Cookies can be observed easily using Chrome's developer tools.

You'll also want to keep these things in mind:

Get in the loop!

Join my email list to get new articles delivered straight to your inbox.

No spam — guaranteed. You can leave at any time.