Context: Derived from the jsDeliver source of minimal-analytics, I created tag.js which has evolved into a more advanced self-hosted substitute with basic dataLayer functionality and most gtag() configuration fields, with roughly 90% web features, including all GA4 Enhanced Measurements, combined into a light 5.5k gzipped size (10KB minified original).
My goal is not to ask for changes, or to submit pull request; as I am not very savvy in Typescript anyway, and there are many fundamental flaws to address... This is a tweet follow-up, to try and point out the core issues I encountered along the way, working from the minimal-analytics js source. (For helpful reference, I posted tag.js as a private gist at the moment.)
Current GA4 mismatch or misconceptions:
-
sessionStorage is not adequate as it's not multi-tab compatible (single window only). GA4 cookies provide full compatibility with multiple tabs or windows. localStorage only is better suited for all parameters that need storage.
-
The fv firstVisit is a function of is_new_to_site not is_new_session.
-
The _s hit count is the number of events sent during a page view session. Not just a static 1. e.g. A scroll event after page_view would qualify as _s=2
-
The sid sessionId does not change until a new session starts. It's the last part of the permanent _ga cookie representing the sessionStart timestamp. @thyngster has a lot of helpful references on his Google Analytics 4 Measurement Protocol CheatSheet.
-
The sct session count is accurately stored. However the way it works, is that it's only incremented on inactivity after a 30 minutes default from the sessionStart (sid) timestamp. See this tweet for additional context.
-
seg sessionEngagement is complex. In brief, it starts with 0 and keeps switching, with 'conversion' event exceptions.
-
The beforeunload event is not reliable. I opted with pagehide at the moment, alongpageshow for auto page_view(s).
-
Unless I am missing something, you can much simplify that overkill scroll percentage function with the following:
Math.round(100 * Math.abs(document.documentElement.scrollTop / (document.documentElement.scrollHeight - document.documentElement.clientHeight)))
-
Per my tests and implementation, ep.search_term is not a parameter sent along other events (such as page_view), and only one event name at a time is supported. ep.search_term is either sent in the beacon payload as a batched parallel event, or a separate view_search_results event but not together by default, as it is now.
Context: Derived from the jsDeliver source of
minimal-analytics, I createdtag.jswhich has evolved into a more advanced self-hosted substitute with basic dataLayer functionality and mostgtag()configuration fields, with roughly 90% web features, including all GA4 Enhanced Measurements, combined into a light 5.5k gzipped size (10KB minified original).My goal is not to ask for changes, or to submit pull request; as I am not very savvy in Typescript anyway, and there are many fundamental flaws to address... This is a tweet follow-up, to try and point out the core issues I encountered along the way, working from the
minimal-analyticsjs source. (For helpful reference, I posted tag.js as a private gist at the moment.)Current GA4 mismatch or misconceptions:
sessionStorageis not adequate as it's not multi-tab compatible (single window only). GA4 cookies provide full compatibility with multiple tabs or windows. localStorage only is better suited for all parameters that need storage.The
fvfirstVisit is a function ofis_new_to_sitenotis_new_session.The
_shit count is the number of events sent during a page view session. Not just a static1. e.g. Ascrollevent afterpage_viewwould qualify as_s=2The
sidsessionId does not change until a new session starts. It's the last part of the permanent_gacookie representing thesessionStarttimestamp. @thyngster has a lot of helpful references on his Google Analytics 4 Measurement Protocol CheatSheet.The
sctsession count is accurately stored. However the way it works, is that it's only incremented on inactivity after a 30 minutes default from thesessionStart(sid) timestamp. See this tweet for additional context.segsessionEngagement is complex. In brief, it starts with0and keeps switching, with 'conversion' event exceptions.The
beforeunloadevent is not reliable. I opted withpagehideat the moment, alongpageshowfor auto page_view(s).Unless I am missing something, you can much simplify that overkill scroll percentage function with the following:
Math.round(100 * Math.abs(document.documentElement.scrollTop / (document.documentElement.scrollHeight - document.documentElement.clientHeight)))Per my tests and implementation,
ep.search_termis not a parameter sent along other events (such aspage_view), and only one event name at a time is supported.ep.search_termis either sent in the beacon payload as a batched parallel event, or a separateview_search_resultsevent but not together by default, as it is now.