The core of this post has been written by our Guest writers, Hamid Eslami and Mohammad Hossein Rouhani. Hamid is a lead front-end engineer and Mohammad is a lead SEO.

Single-page applications (SPA’s) are great, but their various complexities can sometimes cause problems. If not set up correctly, Google Analytics (GA) can mix up paid and organic users, something that causes a range of issues within reporting.

When I researched this issue further, I noticed that GA considers some users who enter the website from Google Ads campaigns as organic users.

In this scenario, the business-focused solely on ad campaigns and certainly wasn’t expecting any organic users. To see them show up was, admittedly, confusing.

Google Analytics data matches Google Ads

To confuse the scenario more, Google isn’t technically misreporting the paid users – at least not entirely. After checking, the number of clicks of the ads panel and GA data is similar. But Google Analytics is still showing users as organic. The question is, where are these users actually coming from? This is what we need to find out. 

What is Rogue Referral?

First of all, you should get acquainted with the rogue referral problem. In short, rogue referral means that Google loses user data and can’t track referral data properly.

Simo Ahava has previously provided an excellent solution to this problem on SPA websites. However, ours is a different solution that should hopefully help you solve the problem in an alternative way.

Before we get started, let me get you familiar with some terminologies.

Generally, website and web applications can handle page rendering in one of two ways:

  • Client-side rendering
  • Client and server rendering

But what do these mean?

Server-side rendering: Server-side rendering (SSR) is when an application is able to change HTML files that are stored on a server into a fully rendered HTML page. This happens when the web browser sends the server a request for information, sending a fully rendered page directly to the client.

Client-side rendering: Client-side rendering is how developers are able to change their websites to fully rendered within the browser with JavaScript. A client-side rendered site creates page routes dynamically and directly within the browser, rather than creating different HTML pages per route.

Client & server-side rendering: Depending on the complexity of the site, websites may need to render some pages from the server and others on the client-side, and both are usually used in this case.

Finally, before we start for the context of the environment that the steps below were carried on, this website has more than 5000 pages, they use Nuxt js and some of the pages are rendered on the client-side while others are rendered on the server-side.

Google Analytics technical implementations

Implementing Google Analytics in a traditional website (server-side rendering)

  1. Just put the Google Analytics script in the header of your website.
  2. Congratulations, your job is done.

Implementing Google analytics in the SPA website (client-side rendering)

According to GA, if your website is a SPA then there is no need to update the two parameters.

You do not have “dl’ or “dr”. It would help not to let these two parameters change as the pages change.




Google says, “a Single Page Application (SPA) is a web application or website that loads all of the resources required to navigate throughout the site on the first page load. As the user clicks links and interacts with the page, subsequent content is loaded dynamically. The application will often update the URL in the address bar to emulate traditional page navigation, but another full page request is never made.”

Step 1: Create a tracker

<!-- Google Analytics -->



(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),



ga('create', 'UA-XXXXX-Y', 'auto');

ga('send', 'pageview');


<!-- End Google Analytics -->

Step 2: Set parameter fixed

Don’t allow this parameter to be updated.



ga('set', 'referrer', ''); // document.referrer

ga('set', 'page', '/'); // document.location.pathname

The final code is:

<!-- Google Analytics -->



(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),



ga('create', 'UA-XXXXX-Y', 'auto');

ga('set', 'referrer', ''); // document.referrer

ga('set', 'page', '/'); // document.location.pathname

ga('send', 'pageview');


Step 3: Check your data

Your application should send the correct data to GA, but the data should always be double-checked on the off chance it hasn’t worked correctly. Note that there are many ways to implement Analytics on SPA websites. For example, you can use tag manager to implement GA in SPA.

How to detect Rogue Referral

Let me introduce you to the rogue referral problem. When we started to fix the problem, my client reported these parameters.

“We see many users come to my website from organic, but in fact, we don’t have any organic users; we collect all of our users from Google Ads.”

“When we check user explorer report in Google Analytics, we find that many users change their source/medium from paid to organic or organic to paid.”

If you face this problem or any of the below, then this article can help you:

  • You see some of your paid users are in the organic user category.
  • In some cases, you see session 0 in Google Analytics User Explorer, or some of the session user sources change from paid to organic.
  • You have a SPA website and you believe the data collected from GA is wrong.

First, you should check your data in Google Analytics. Create segments such as the below to discover the user change medium from paid to organic.

Be careful. This can happen because users might come from ads at 8:00 AM and then come back to this page organically at 8:00 PM.

Next, go to user explore and select the data for the current day and check some of the user IDs.

As you see, in this case, a user comes from organic at 8:39 PM and, in the following session, the user status is changed to paid.

But how?

Imagine this flow:

  1. User clicks on ads in SERP and comes in landing
  3. Next, click on another link, a user navigates to page B

At this time, you should be familiar with this query – how can Google separate organic users and paid users?

In general, if you click on the ads link, Google Ads will change some of the query parameters in your URL. This is generally done using Google auto-tagging for google ads. If Google finds some parameters such as campaign, gclid, source, medium, etc., it then can separate understand if the user is organic or paid.

In this case, Google cannot detect the medium of a user. The first user comes from paid but, after the user navigated to another page, Google lost the data of the user.

To understand better, follow these steps:

  1. Search keyword in Google and find the ads link
  2. Open your developer console in Chrome
  3. Tap on the network tab, activate the record button, and click on the ads link
  4. In network request, search collection request.

Finally, click on collection request and find this parameter in the payloads tab.

Let me introduce this parameter:





If you come from the ads, you should see gclid or Campaign Source etc., in the dl parameter.

  • User clicks on ads link
  • The user is now on page A (you should see all parameters such as gclid and UTM in dl parameters)
  • User clicks on a button on page A and, after that, comes to page B. This is important to keep all parameters such as gclid and UTM still in dl parameters.

Be careful it’s not related to the URL in the search box on your browser

This image doesn’t see any parameters in the URL, but the request displays all parameters in the collection.

In my case, the architecture of the app is that we have many pages – some handle on the client-side and some on the server-side.

You should know it’s a technical issue and not a Google bug because your page can’t send parameters from the first page to another page.

You should check it first and fix it if needed.

How can you fix it?

It is essential to know it’s related to many things, such as front-end framework, backend framework, and server configuration.

If we face a big project, this website handles the page with NUXT.

Imagine a user comes from the ads link – it’s important to know how Google handled this parameter to select the source medium of the user. Ultimately, Google wants to know whether users come from organic or paid channels.

How can I check it?

Open network tab in chrome developer tools. You should first check the Google collections request in the network tab in each page. Secondly, on each page, check the document referrer and document location.

By default, Google should handle all parameters correctly. In the below image, you can see how your website should be sent or how it should store parameters on each page.

If you want to check this topic on your website, open network, tap on chrome developer tools, and check dl,dr for a paid campaign and organic.

Correct handling of parameters

As you can see in the last picture, users come from ads channels, and on each page, Google can recognize user sources.

But if your website can’t handle this parameter correctly, you’re faced with rogue referral.

Rogue Referral - Incorrect handling
Incorrect handling of parameters

As you see in the last picture, although the user comes from the ads link, the user has been allocated as organic after navigating to the landing page.

Rogue Referral - Handling of Google Organic Click
Handling of Google Organic Click


To keep these parameters on all pages, you should set dr and dl to the first parameters when users come from ads.

You should first save dr and dl in session storage and set these parameters in the Google Analytics script.



const dlc = document.location.href;

const drcf = document.referrer;

const all_data ={




const anly_cu = JSON.stringify(all_data)

sessionStorage.setItem(“anly_cu”, anly_cu);



<!– Google Analytics –>



(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),



ga(‘create’, ‘UA-XXXXX-Y’, ‘auto’);

ga(‘set’, ‘referrer’, dlc); // now send document referrer from session storage

ga(‘set’, ‘page’, drcf);

ga(‘send’, ‘pageview’);


As you can see in the below image, we store many parameters in session storage.

In my case, after we set this parameter, the problem solves itself. After that, we checked Google Analytics other reports.

Before we fixed this problem:

After we fixed the problem:


After we change Google Analytics dl, dr, we solve the problem. We could reduce the percentage of source and medium change from 30 to 2.

If you want to develop a website, be careful of how the page handles parameters.

In some of the cases, redirecting from one page to another can impact the Google Analytics report. Be careful – all parameters should be stored in dl, even page redirects.

In some of the cases that the server configuration can impact, their server can’t handle UTM parameters.