Skip to content

How to keep your returning user’s legacy data when switching domain name

David Vallejo

When we’re switching a site domain name we always have in mind some basic steps to take in mind so the migration doesn’t end being a mess. One of those steps is usually 301-ing our old domain content to the new one, but we never think on how will this affect our current Google Analytics data.

Universal Analytics cookie is based on the domain hostname, so if we switch the current domain a new cookie set will be created along with a new client ID, forcing that all the visits we redirect will end being new visitors. This mean we’ll be losing ALL our previous attributions/history data for returning visitors., doh!

This time, we’ll try to mitigate this problem using Google Tag Manager and some Mod Rewrite (htaccess) magic.

We’ll be using Apache’s Rewrite module to read the current user “_ga” cookie and passing it along our redirection, then from GTM we’ll force the clientId within our tracker in order to keep our old users clientId for our new domain 🙂

Below you can find our .htaccess. As you can see we check for _ga cookie value, and then we redirect the user to the new domain with a new parameters named “_mga” , that is going to hold the _ga cookie value and the timestamp.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} _ga=([^;]+) [NC]
RewriteRule ^(.*)$$1?__mga=%1\.%{TIME} [R=301,QSA,L]
RewriteRule ^(.*)$$1 [R=301,QSA,L]

You may be asking yourself about why we are adding the current timestamp (%{TIME}) as a parameter value. The reason is pretty simple, we don’t want someone sharing that url to someone else and end having a lot of users sharing the same clientId, do we?

We’ll use that value later on Google Tag Manager to check is the redirection was generated less than 120 seconds ago if not we’ll just return any value. This is how native Universal cross-domain feature works too!

if ({{__mga.timestamp}}) > 120)

If _mga.timestamp and current user timestamp values substract is higher than “120”,  it means it was generated more than 2 minutes ago, so we don’t want to push any clientId back on this case.

The current format for the %{{TIME}} value from mod rewrite is the following:


And it will likely be using the UTC timezone. This is important since the check will be made client-side, and we’re gonna need to check the current user time in UTC time, not the current client timezone.

GTM Configuration

On the Google Tag Manager side, we’ll need one variable that will take care of grabing the _mga value,  and from there we’ll get the clientId and the link generation time.

Then we’ll be checking the current user browser’s UTC timestamp to see if this link was generated less than 120 second ago, to know if we should be returning any value.

Grab the variable code bellow:

    // Let's grab our custom linker value from QS
    var _mga_linker_value =[^&]*)/)[1].split('.').pop();

    // convert the YYYYMMMDDHHMMSS date to timestamp format
    var _mga_date = new Date(_mga_linker_value.slice(0, 4), _mga_linker_value.slice(4, 6) - 1, _mga_linker_value.slice(6, 8), _mga_linker_value.slice(8, 10), _mga_linker_value.slice(10, 12), _mga_linker_value.slice(12, 14));

    // add the current browser timezone offset
    var _mga_timestamp_utc = Math.round(_mga_date*1/1000)-new Date().getTimezoneOffset()*60;

    // browser UTC time
    var _browser_timestamp_utc = new Date()*1;

    // the total seconds diff, between linker creation time and current user's browser time
    var _linking_offset_in_sec = Math.round(_browser_timestamp_utc/1000 - _mga_timestamp_utc);

    // force the clientId value ONLY if the time difference is less than 2 minutes

Now we only need to use the returned value by this variables as the “clientId” value on our tracker this way:

Of this this may not be only applied for Google Analytics but for any other cookie value you want to keep, just modify the code to grab any other cookie value you may need