How to get source and medium programmatically with JavaScript - just like Google Analytics

To make smart marketing decisions, you need to know what the Return On Marketing Investment (ROMI) is. When you're a webshop that does immediate transactions, it's easier to set up Google Analytics to serve you. However, if you need to understand longer customer relationships, Lifetime Values, etc, you need to get your hands on raw data.

The obvious idea that comes to mind is: "I just need to get the source, medium, campaign etc. data per each visitor" and you quickly realize that Google Analytics doesn't allow you to do that.

You need a custom solution. I have found two online that solve the problem

  1. This one with FirstSession and ReturningSession cookies set
  2. The Lunametrics one, which is a bit more verbose, but has a more extensive list of search engines

These solutions are just fine, but, no-one's maintaining them. They're old. They don't evolve. And they don't support other paid channels than Google search. What about Bing? Facebook?

Also, both of these solutions combine two very separate problems into one:

  1. Deciphering what the traffic data is (source, medium, campaign etc), and
  2. Storing it for later retrieval.

And the 2nd part happens through cookies. It's 2022 and Cookies could soon be dead. Then what?

VisitDataJs: the open source Google Analytics data emulator

I've written a small javascript open source library to tackle the first problem - getting Google Analytics data such as source and medium, programmatically through JavaScript - called VisitDataJS.

Usage is simple and you should refer to the readme, but simply include the javascript and run it, like so:

<script src=""></script>
	console.log( visitData.get() );

Here's the results for you personally, how you arrived to this page:


GlobalStorage: the open source, cross domain browser storage that doesn't run on cookies

GlobalStorage is an open source javascript library you can include from anywhere, and use it just like you use the browser's localStorage, except that you can access the same data from any website! Here's how it works:

<script src=""></script>
  globalStorage.init().then(() => {
    globalStorage.setItem("your-key-name", { foo: "bar" } );

The above code will store the object { foo: "bar" } to the key 'your-key-name', which can then be fetched from another web page by calling getItem. You should check the readme for the library as there are some default behavior of this you need to be aware of, such as how do you control who has the right to read the data.

Years ago already, Zendesk did a marvelous job with Cross Storage, but there was one thing I think they got wrong: forcing you to host your own 'Hub' file to have control over who has access to your data. So I took a lot from Zendesk's cross storage but made a completely new version that achieves something similar, but more easily. While Zendesk's Cross Storage requires you to also host a hub.html file and configure it for yourself, my solution works easily without the need for you to host your own file. You can just use the one I hosted - but you still have control over your data.

Incredible value having access to this data

We've gained an incredible amount of value by having access to this data. It's not about being able to replicate GA:s reports, but instead, enriching our user base with new dimensions that we can use as a lens into business metrics. For example:

  • Are users acquired by paid acquisition more likely to churn than those who we acquire by organic means? 
  • Which campaigns are most likely to convert people into active and paying customers?
  • What is the lifetime value of a new conversion, split by cpc vs organic?
What we've found out for example is that CPC traffic can convert, often better than organic, but the bottom of the funnel often performs worse. We've been able to identify Google Ads campaigns that bring in signups, but never bring paying customers, and cancel them. We've seen how affiliate networks we've tried have lead to fraudulent accounts and no business. These things are difficult to prove without granular, per account data.


Popular posts from this blog

Snowflake UPSERT operation (aka MERGE)