TL;DR, Quick Answer
8 min readClickstream data is the unaggregated hit-level export from an analytics platform: one row per interaction, carrying a timestamp, a visitor identifier, a URL, a user agent and often a raw IP address. Adobe delivers it through data feeds with columns such as hit_time_gmt, visid_high, post_page_url and user_agent; Google Analytics 4 delivers the equivalent through the BigQuery export with event_timestamp, event_name and user_pseudo_id. Because every row still carries an online identifier, GDPR Article 4(1) and California Civil Code 1798.140(v)(1)(F) both bring the file inside their definitions of personal data, which is what separates it legally from an aggregated report.
What is clickstream data?
Every row of clickstream data is one interaction by one visitor at one moment, stored without aggregation, with the identifier, the timestamp and the URL all still attached. Nothing has been counted, averaged or rolled up. A report tells you that 4,812 sessions landed on /pricing last week. The clickstream underneath that report is 4,812 separate rows, each one naming a visitor, a second in time and a page, plus dozens of columns describing the device and the traffic source.
The name comes from the shape of the thing. Sort those rows by identifier and then by timestamp and you get a stream of clicks: the literal sequence of what one person did, in order, on your site. That sequence is the raw material every other analytics number is computed from. It is also the reason behavioral analytics exists as a discipline separate from reporting, because questions about order and sequence cannot be answered from a table of totals.
What is in a single clickstream record?
A clickstream record carries a timestamp, a visitor identifier, a hit identifier, the URL, the referrer, the device and the values of every custom variable that was set on that hit. Adobe Analytics publishes the full column list for its data feeds, and these are its own descriptions:
| Column | Adobe's description |
|---|---|
hit_time_gmt | "The timestamp of the hit Adobe data collection servers received the hit, based in UNIX time." |
hitid_high | "Used with hitid_low to identify a hit." |
visid_high | "Used with visid_low to uniquely identify a visitor." |
visit_num | "Starts at 1, and increments each time a new visit starts per visitor." |
page_url | "The URL of the hit." |
post_page_url | "Stripped for link tracking image requests." |
page_event | "The type of hit that is sent in the image request (standard hit, download link, custom link, exit link)." |
user_agent | "The user agent string sent in the HTTP header of the image request." |
ip | "The IPv4 address, based on the HTTP header of the image request." |
geo_city | "The name of the city that the hit came from, based on IP." |
referrer | "The Referrer dimension." |
post_evar1 | Custom variable 1 after server-side processing, one of eVar1 through eVar250 |
Adobe describes the whole mechanism in one line: "Data feeds are a powerful way to get raw data out of Adobe Analytics," delivered "in hourly batches at the conclusion of each hour, or in daily batches at the conclusion of each day."
Google Analytics 4 ships the same idea under different names through its BigQuery export. There the row-level fields are event_timestamp, "the time (in microseconds, UTC) when the event was received by Google Analytics"; event_name, "the name of the event"; and user_pseudo_id, "the pseudonymous id (e.g., app instance ID) for the user. A unique identifier that is assigned to a user when they first open the app or visit the site." Parameters hang off each row as repeated event_params.key and event_params.value.string_value pairs, and geo.city is populated "based on IP address."
Two vocabularies, one structure. Adobe counts hits, GA4 counts events, and both give you one line per thing that happened.

How does clickstream data differ from aggregated analytics?
Aggregated analytics answers questions you wrote down before collection; clickstream data answers questions you think of afterwards. That is the entire trade. A report has already decided which dimensions pair with which metrics, and a number that was never computed cannot be recovered from it. The raw rows have made no such decision, so you can join, filter and re-sequence them however a new question demands.
| Aggregated report | Clickstream export | |
|---|---|---|
| Grain | One row per dimension combination | One row per hit or event |
| Identifier | Removed or thresholded | Present on every row |
| Sequence | Lost | Preserved by timestamp |
| New questions | Need a new collection plan | Answered by a new query |
| Size for 1M monthly sessions | Kilobytes | Tens of gigabytes |
| Who reads it | Anyone with the UI | Anyone with SQL and warehouse access |
Google enforces the split in its own product. Its data retention setting offers "2 months" or "14 months" for user-level and event-level data, and Google states that "the data retention setting does not affect standard aggregated reports (including primary and secondary dimensions) in your Google Analytics property." The aggregates outlive the rows they came from, which is exactly the point: the aggregates stopped being personal data and the rows never did. See Google Analytics data retention for what expires and when.
Sessionisation is the other difference worth naming. A clickstream file contains no sessions at all, only ordered hits; the session is a rule applied to those hits later. Change the rule and the session count changes without a single row moving, which is the mechanism behind what counts as a session.
Which privacy obligations attach to clickstream data?
Clickstream data is personal data in the EU because each row carries an online identifier. GDPR Article 4(1) defines personal data as "any information relating to an identified or identifiable natural person," where an identifiable person "is one who can be identified, directly or indirectly, in particular by reference to an identifier such as a name, an identification number, location data, an online identifier." Recital 30 removes the ambiguity about what an online identifier means: "Natural persons may be associated with online identifiers provided by their devices, applications, tools and protocols, such as internet protocol addresses, cookie identifiers or other identifiers." Your visid_high column and your user_pseudo_id column are those identifiers, and the ip column is named in the recital outright. The point is worked through in whether an IP address is personal data.
California arrives at the same place by a different route. Civil Code 1798.140(v)(1)(F) lists among the categories of personal information "Internet or other electronic network activity information, including, but not limited to, browsing history, search history, and information regarding a consumer's interaction with an internet website application, or advertisement." A clickstream file is browsing history in the most literal sense available.
Three duties follow directly. Article 5(1)(c) requires that personal data be "adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed," which makes every column you collect because it was in the default schema a column you have to justify. Article 5(1)(e) requires that data be kept "in a form which permits identification of data subjects for no longer than necessary," which turns retention from a storage-cost decision into a legal one. Article 17(1) gives the data subject "the right to obtain from the controller erasure of personal data concerning him or her without undue delay," which means you need a way to find every row belonging to one identifier across every partition, warehouse copy and backup you made.

Does collecting it require consent?
Storing or reading the identifier on the visitor's device requires consent in the EU regardless of whether the data is personal. Article 5(3) of Directive 2002/58/EC covers "the storing of information, or the gaining of access to information already stored, in the terminal equipment of a subscriber or user," and allows it "only on condition that the subscriber or user concerned has given his or her consent, having been provided with clear and comprehensive information." The rule attaches to the act of touching the device, not to the sensitivity of what you learn.
Flowsery
Start Your 14-Day Free Trial
Real-time dashboard
Goal tracking
Cookie-free tracking
The same article carves out two exemptions: storage or access "for the sole purpose of carrying out the transmission of a communication over an electronic communications network, or as strictly necessary in order for the provider of an information society service explicitly requested by the subscriber or user to provide the service." Analytics measurement is not the service the visitor explicitly requested, which is why cookie-based measurement sits behind a banner. Collection that reads nothing from the device does not engage Article 5(3) at all, which is the structural argument for cookieless tracking.
Can you strip the identity out and keep the file?
Removing direct identifiers produces pseudonymised data, not anonymous data, and pseudonymised data stays in scope. Hashing visid_high still leaves a stable key that links every row of one person's history together, and a stable key that supports linkage is the definition of a pseudonym rather than an erasure. Only irreversible aggregation that makes single-person rows unrecoverable takes a file out of scope, and that is a destructive operation by design. The distinction, and what each one costs you analytically, is set out in pseudonymisation versus anonymisation.
Practical mitigations exist between those poles. Truncate the IP octet before writing the row rather than after. Drop user_agent if you only ever read the parsed browser name from it. Set retention on the raw table shorter than on the derived aggregates. Each of those is a direct answer to Article 5(1)(c), and each is easier to do at collection time than to retrofit across a warehouse.
Frequently asked questions
Is clickstream data personal data under the GDPR?
Yes, whenever each row carries a stable visitor identifier or an IP address. GDPR Article 4(1) counts anyone identifiable "indirectly" through "an online identifier," and Recital 30 names internet protocol addresses and cookie identifiers explicitly as examples of those identifiers.
What is the difference between clickstream data and a server log?
A server log records requests the server handled; clickstream data records interactions the analytics tag observed. The log misses cached pages, scroll events, clicks that fire no request and any custom variable, while the clickstream misses bots and assets the tag never saw.
How much clickstream data does a mid-size site produce?
Volume scales with hits, not with visitors. A site averaging six hits per session and one million sessions a month writes six million rows a month, and Adobe data feeds and the GA4 BigQuery export both carry well over a hundred columns per row before any custom variables are added.
Do aggregated reports survive when raw rows are deleted?
In Google Analytics 4 they do. Google states that the data retention setting "does not affect standard aggregated reports (including primary and secondary dimensions) in your Google Analytics property," so aggregates computed before expiry remain readable after the event-level rows are gone.
Does consent law apply if I never store a cookie?
Article 5(3) of the ePrivacy Directive attaches to "the storing of information, or the gaining of access to information already stored, in the terminal equipment" of the user. Collection that neither writes to nor reads from the device does not trigger that article, though the GDPR still governs whatever personal data you process server side.
Which columns are the ones worth dropping first?
Start with ip and user_agent. Both are named or implied in Recital 30's list of identifiers, both are usually consumed only in parsed form as city and browser, and both can be reduced at collection time without changing any downstream report.
How often does an analytics platform deliver clickstream data?
Adobe pushes its data feeds "in hourly batches at the conclusion of each hour, or in daily batches at the conclusion of each day." GA4 ships the same row-level detail through its BigQuery export, following the identical one-row-per-event structure under different column names.
What is the difference between a hit and an event in clickstream data?
A hit is Adobe's name for one clickstream row, and its page_event column marks whether it was a standard hit, a download link, a custom link, or an exit link. GA4 calls the same row an event and records its name in the event_name column. The vocabulary differs, but the grain is identical, one line per thing that happened.
Can Adobe and GA4 clickstream exports be mapped to each other?
The anchors line up loosely: hit_time_gmt matches event_timestamp, in seconds against microseconds, visid_high matches user_pseudo_id, and page_url matches the page_location parameter. Both keep the same three anchors, a timestamp, an identifier, and a URL or event name, just under different labels.
Does a clickstream row reveal what device a visitor used?
Adobe's rows carry a raw user_agent string plus dozens of device and traffic-source columns, while GA4's BigQuery export ships parsed device fields instead. Adobe's user_agent column stores the string exactly as sent in the HTTP header, before anyone parses it into a device name. Nothing about it is aggregated, so the device behind a single visit stays visible row by row.
Was This Article Helpful?
Let us know what you think!
See us more often in Google
One click marks Flowsery as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.
Before you go...
Flowsery
Revenue-first analytics for your website
Track every visitor, source, and conversion in real time. Simple, powerful, and cookie-free.
Real-time dashboard
Goal tracking
Cookie-free tracking
Related Glossary Terms


What Session Replay GDPR Compliance Actually Requires of You
A session replay GDPR review turns on four things: an Article 6 lawful basis, Article 9 special category data, ePrivacy Article 5(3) consent, and a DPIA.


Reversibility decides pseudonymisation vs anonymisation under the GDPR
Reversibility decides pseudonymisation vs anonymisation. Article 4(5) data stays personal data. Recital 26 anonymous data leaves the GDPR for good.


Under the GDPR and the CCPA, is an IP address personal data?
Under the GDPR, is an IP address personal data whenever the site operator has legal means to identify the visitor, the CJEU held in Breyer. US law is split.


How an Attribution Window Decides Which Touchpoints Get Paid
Move the attribution window from 7 to 90 days and one $1,800 order pays three different sets of channels. See the arithmetic and the current platform defaults.


One Page of Traffic Settles Bounce Rate vs Exit Rate
Reading bounce rate vs exit rate comes down to two denominators. One pricing page returns a 40% exit rate and a 15% bounce rate in the same week.


Working the Conversion Rate Formula on Real Traffic
The conversion rate formula is conversions divided by sessions or unique visitors, times 100. One week of traffic run through both denominators gives two.
Related Articles


How Cookieless Analytics Counts Visitors Without an Identifier
A cookieless analytics tool counts visitors without storing an identifier in the browser. What that removes, what it costs, and why fingerprinting fails.


The Test That Settles Data Controller vs Data Processor
The GDPR test for data controller vs data processor is who determines the purposes and means. What each role signs, owes, and does when a breach hits.


Reading Engagement Rate in Google Analytics 4
GA4 reports engagement rate as engaged sessions divided by total sessions. A session counts as engaged at 10 seconds, one key event, or two page views.

