One of the hard-and-fast rules in Google Analytics is that once hits have been collected and processed into your data properties, those hits are untouchable. This means that if you mistakenly collect duplicate or incorrect transactions, PII traffic, or referral spam, for example, it's extremely difficult, if not downright impossible, to purge or change this data in Google Analytics.

Another staple of Google Analytics’ strict schema is that displacing hits in time is also very difficult. Hits are digested as they come in, and they are placed in time in the order of processing. If Google Analytics collects hit B after hit A, then it will be reported as having occurred in that order, too.

However, there is a feature in the Google Analytics collection protocol that does allow you to realign a hit in the past timeline. So even if hit B is sent after hit A, you can still have it enter data tables with a timestamp that precedes hit A.

This feature is called Queue Time, and because of some fairly confusing documentation, it has been either easily ignored or misunderstood.

In this article, I'll explain how Queue Time works, and how you can use it to realign hits.

What is Queue Time

Queue Time is a parameter in the Measurement Protocol (qt). It takes a zero or a positive integer number as its value.

With the Queue Time parameter, you can instruct Google Analytics to process the hit so that it would appear as having occurred as many milliseconds ago from the collection moment as specified by the parameter.

For example, if you send a hit to Google Analytics at precisely 12:35:05 with the following qt value:

&qt=5000

The hit will have a timestamp of 12:35:00, as you instructed Google Analytics to assign the hit with a timestamp 5 seconds (5000 milliseconds) earlier than it was actually collected.

This is a very useful parameter, and is actively used in things like service workers to correctly place hits collected when the network was down, and with mobile app analytics to make sure that batched and deferred hits are collected correctly.

You could also use it with other offline data collection systems like point-of-sales machines, in order to place a transaction in Google Analytics at the actual time of the transaction, even if you send the data in batches every evening after business hours.

Limitation: only same-day hits

And now we get to the biggest source of confusion.

The documentation states that Values greater than four hours may lead to hits not being processed, but it doesn't really say what this means.

To clarify this, here's the main limitation of Queue Time:

Queue Time only lets you send hits to the current day (with one major caveat, coming right up).

Thus, for any day that starts at 00:00:00 (midnight) and ends at 23:59:59, the hit that uses Queue Time must also occur within that time window.

However. There are two catches.

Catch 1: You can send hits until 4 a.m. of the following day

The time window is artifically extended to 03:59:59 of the following morning.

Thus, if you want to send a hit so that it happened on Friday, March 6th 2020, the hit must be sent either during March 6th, or no later than 03:59:59 in the morning of March 7th.

This means that the maximum value for Queue Time is 100799000 milliseconds. That's 27 hours, 59 minutes, and 59 seconds. That hit must be sent at 03:59:59, and it will be processed by Google Analytics as having occurred at 00:00:00 the previous day.

Catch 2: The concept of “time” is bound to the timezone settings of the Google Analytics view

And here's where it gets tricky.

The only way for your 100799000 millisecond Queue Time will work is if you send it at 03:59:59 of the following day in the timezone of the Google Analytics view that will report the hit.

As you can probably understand, this will lead to issues if you have a property with multiple views in different timezones.

Four hours is the maximum length of time that is guaranteed to work

Perhaps now the weird four-hour processing limitation from the Measurement Protocol documentation is a bit clearer.

If you use Queue Time, then a maximum value of 14400000, that's 4 hours, is guaranteed to work. This is because regardless of timezone in the Google Analytics property, a hit with a Queue Time of 14400000 is always guaranteed to either fall within the previous day (if sent no later than 03:59:59 the following morning), or the current day (if sent at 04:00:00 in the morning or later).

Let's imagine you send a hit with a Queue Time of 14400000, and the timezone you send it in is in UTC. The date is March 7th, and the local time is 03:59:59 in the morning.

Here's how the hit is processed from the point-of-view of a Google Analytics view that receives the hit.

Google Analytics timezone Date and time of hit sent Date and time of hit processed Valid
UTC March 7, 03:59:59 March 6, 23:59:59 Yes
UTC-06:00 March 6, 21:59:59 March 6, 17:59:59 Yes
UTC+01:00 March 7, 04:59:59 March 7, 00:59:59 Yes
UTC+10:00 March 7, 13:59:59 March 7, 09:59:59 Yes

See how regardless of timezone, the hit is valid. That's because the hit is sent and processed either during the same day, or the hit is sent before 4 a.m. the following day, per the Google Analytics timezone.

Let's try a value larger than that. We'll attempt to send the hit 7 hours into the past - that's 25200000 milliseconds. We're still in UTC, the date is still March 7th, and it's still 03:59:59 in the morning.

Google Analytics timezone Date and time of hit sent Date and time of hit processed Valid
UTC March 7, 03:59:59 March 6, 20:59:59 Yes
UTC-06:00 March 6, 21:59:59 March 6, 17:59:59 Yes
UTC+01:00 March 7, 04:59:59 March 6, 21:59:59 NO
UTC+10:00 March 7, 13:59:59 March 7, 06:59:59 Yes

All other hits are valid except the one collected in the Google Analytics view in the UTC+01:00 timezone. This is because the hit is queued to have happened during March 6, but it's sent after 4 a.m. on March 7th.

How to implement

To add the Queue Time parameter to a hit, you simply need to set it in the hit itself. If you're using Google Tag Manager, it's as simple as adding a new Fields to set that looks something like this:

The field name is &qt, and the value is the delta in milliseconds of when the hit should be processed vs. when it is sent.

With analytics.js, you'd set it like this:

ga('send', 'event', 'Some Category', 'Some Action', {'&qt': 5000});

As far as I know, there is no way to set arbitrary Measurement Protocol parameters in a gtag.js call.

Summary

The Queue Time parameter lets you send hits to the past with Google Analytics. As such, it's a fairly powerful utility. There are many reasons why you'd want to delay hits from being sent at time of collection, only to still be processed in the correct time within the Google Analytics timeline.

The catch is that you can only append hits to the current day. There's no way to send hits more than a day into the past, unfortunately.

Google Analytics extends the time window to stretch until 4 a.m. of the following day, but the problem is that the concepts of “current day” and “following day” are established by the timezone of the settings of each individual Google Analytics view.

Thus when you use the Queue Time parameter in Measurement Protocol hits, you need to either correlate the client time (time of the browser or machine sending the hits) with the time of the Google Analytics view to which you send the hits. If you can't do this correlation, then you should make sure to only send hits a maximum of four hours into the past, because those are the only types of queued hits that are guaranteed to work.