ENG-9611: defer tracking/analytics scripts so they don't block render#6568
ENG-9611: defer tracking/analytics scripts so they don't block render#6568adhami3310 wants to merge 2 commits into
Conversation
External `src` trackers get `async_=True` (gtag loader, clearbit). Inline trackers get `type="module"` so the browser defers them until after HTML parsing (posthog, koala, common_room, rb2b, unify, default, gtag init). Also switches all of these from `rx.script` to `rx.el.script`. The trackers are placed via `App(head_components=...)` which is compiled directly into `<Head>`, so the Helmet wrapper that `rx.script` adds is redundant runtime cost. `gtag_report_conversion` is intentionally left non-module — it defines a global function called by name from `onclick` handlers.
Greptile SummaryThis PR defers all telemetry/analytics scripts to eliminate render-blocking by applying
Confidence Score: 5/5Changes are safe to merge; all inline scripts correctly expose their globals via explicit The previous concern about No files require special attention. The one file worth a second glance is Important Files Changed
Reviews (2): Last reviewed commit: "fix: assign gtag to window so type=modul..." | Re-trigger Greptile |
A top-level `function gtag(){}` in a type=module script is module-scoped,
not installed on `window`. That breaks `gtag_report_conversion` and any
page code that calls `gtag('event', ...)` before the external gtag.js
loader finishes — `window.gtag` is undefined and the call throws.
Assign `window.gtag` explicitly. The `|| window.gtag` guard handles the
case where the async external loader executes before the deferred module
inline (so we don't clobber gtag.js's real implementation).
Caught by Greptile on PR #6568.
|
@greptile |
Summary
srctracker scripts (gtag loader, clearbit) getasync_=Trueso they no longer block HTML parsing while downloading.type="module", which the browser defers until after HTML parsing.rx.scripttorx.el.script. These trackers reach the DOM viaApp(head_components=...), whichreflex/compiler/utils.py:create_document_rootcompiles straight into<Head>— so the Helmet wrapper thatrx.scriptadds is redundant reconciliation cost.gtag_report_conversionis intentionally left non-module: it defines a globalfunction gtag_report_conversion()that pageonclickhandlers call by name; module scope would hide it fromwindow.Linear: ENG-9611
Cross-repo follow-up
get_common_room_trackersis currently rendered insiderx.theme(rx.cond(...))in two consumers (cloud, flexgen) rather thanhead_components. The oldrx.script/Helmet wrapper hoisted it to<head>regardless; switching torx.el.scriptmeans it now stays in the body where the theme renders it. The IIFE is idempotent andtype="module"defers the same way regardless of DOM position, so it still works — but the head/body location changes for those two consumers.A follow-up PR to cloud and flexgen should move the
get_common_room_trackers(...)call intohead_components=and adapt therx.cond(~AuthState.in_session & is_prod_mode(), ...)gate accordingly.Test plan
uv run ruff check .cleanuv run ruff format .cleanuv run pyrightclean on the telemetry packageget_pixel_website_trackers()and confirm tracker requests are no longer in the render-blocking section of the waterfall