Skip to content

fix(analytics): bypass Cloudflare Rocket Loader for Mixpanel snippet#5

Merged
rosuH merged 1 commit into
mainfrom
fix/mixpanel-rocket-loader
Jul 6, 2026
Merged

fix(analytics): bypass Cloudflare Rocket Loader for Mixpanel snippet#5
rosuH merged 1 commit into
mainfrom
fix/mixpanel-rocket-loader

Conversation

@rosuH

@rosuH rosuH commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Symptom

PR #4 fixed the SDK URL, but Mixpanel still shows zero data after deploy.

Root cause — Cloudflare Rocket Loader

The live HTML shows Rocket Loader rewrote our analytics <script>:

- <script>
+ <script type=\"bbb8cf785a6518761e24ebb8-text/javascript\">

Rocket Loader changes every inline script's type to a hashed-prefixed variant, which the browser treats as unknown → does not execute. It then defers execution to its own loader.

For the Mixpanel snippet this is fatal: the IIFE that injects the SDK never runs, so window.mixpanel is never initialized, the SDK is never loaded, and every downstream mixpanel.track(...) call is a no-op. Zero events reach Mixpanel.

Evidence the rest of the chain is fine

Tested directly (bypassing Rocket Loader):

So the only remaining blocker is Rocket Loader suppressing the inline init.

Fix

Add data-cfasync=\"false\" — Cloudflare's official escape hatch that says "run this script normally, don't touch it":

- <script>
+ <script data-cfasync=\"false\">

Applied to both `site/index.html` and `web/index.html`. Also expanded the comment to explain why the attribute is there, so nobody removes it later.

After merge

  1. Cloudflare Pages rebuilds automatically (Git integration)
  2. Open https://fx.rosuh.me, DevTools → Network → filter `mixpanel`
  3. Should see POST to `api-js.mixpanel.com/track/` returning `1`
  4. Mixpanel Live View should light up within ~30s

Root cause of "no data in Mixpanel": Cloudflare Rocket Loader rewrites every
inline <script>, changing type="text/javascript" into type="<hash>-text/javascript".
The browser then refuses to execute it, so the Mixpanel IIFE + mixpanel.init(...)
never run — the SDK is never injected and zero events are sent.

The fix is the standard Cloudflare escape hatch: data-cfasync="false" tells
Rocket Loader to leave this script alone and let the browser run it immediately,
in document order. Verified the rest of the chain is healthy:
  - SDK URL mixpanel-2-latest.min.js → HTTP 200 (fixed in PR #4)
  - api-js.mixpanel.com/track/ → returns 1 (accepts events)
  - token/region correct (US decide endpoint 200)

So this is the last remaining blocker.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 6, 2026

Copy link
Copy Markdown

Deploying fx-lab with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0a16886
Status: ✅  Deploy successful!
Preview URL: https://b55e8eec.fx-lab.pages.dev
Branch Preview URL: https://fix-mixpanel-rocket-loader.fx-lab.pages.dev

View logs

Copilot AI review requested due to automatic review settings July 6, 2026 13:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a168866da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/index.html
data-cfasync="false" tells Cloudflare Rocket Loader to leave this script alone (run immediately, in document order).
Without it, Rocket Loader rewrites <script type> and the inline init never executes → zero events reach Mixpanel. -->
<script data-cfasync="false">
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b){var c=b.split(".");2==c.length&&(b=b[c[0]],a=c[0]]=a[c[0]]||{},a=a[c[0]])}b._q.push({a:d});f("track");f("identify");f("reset");f("register");f("alias");f("people.set");f("people.increment");f("track_charge");f("append");b._i[d]={};a&&"function"==typeof a&&(b._i[d]=a)};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore valid Mixpanel bootstrap syntax

In browsers this inline script now fails to parse because the assignment expression was changed to a=c[0]]=..., so none of the script block runs, including mixpanel.init(...). In the deployed analytics path this leaves window.mixpanel uninitialized and keeps all events at zero despite the Rocket Loader opt-out; the same typo is present in web/index.html as well.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to restore Mixpanel analytics by preventing Cloudflare Rocket Loader from rewriting (and effectively disabling) the inline Mixpanel bootstrap snippet, using Cloudflare’s data-cfasync="false" escape hatch.

Changes:

  • Add data-cfasync="false" to the inline Mixpanel <script> tag so Rocket Loader won’t rewrite/defer it.
  • Expand the inline comment explaining why Rocket Loader must be bypassed for this snippet.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
web/index.html Adds Rocket Loader bypass + explanatory comment to keep the inline Mixpanel init executing.
site/index.html Same Rocket Loader bypass + explanatory comment for the site variant of the HTML.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread web/index.html
data-cfasync="false" tells Cloudflare Rocket Loader to leave this script alone (run immediately, in document order).
Without it, Rocket Loader rewrites <script type> and the inline init never executes → zero events reach Mixpanel. -->
<script data-cfasync="false">
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b){var c=b.split(".");2==c.length&&(b=b[c[0]],a=c[0]]=a[c[0]]||{},a=a[c[0]])}b._q.push({a:d});f("track");f("identify");f("reset");f("register");f("alias");f("people.set");f("people.increment");f("track_charge");f("append");b._i[d]={};a&&"function"==typeof a&&(b._i[d]=a)};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);
Comment thread site/index.html
data-cfasync="false" tells Cloudflare Rocket Loader to leave this script alone (run immediately, in document order).
Without it, Rocket Loader rewrites <script type> and the inline init never executes → zero events reach Mixpanel. -->
<script data-cfasync="false">
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b){var c=b.split(".");2==c.length&&(b=b[c[0]],a=c[0]]=a[c[0]]||{},a=a[c[0]])}b._q.push({a:d});f("track");f("identify");f("reset");f("register");f("alias");f("people.set");f("people.increment");f("track_charge");f("append");b._i[d]={};a&&"function"==typeof a&&(b._i[d]=a)};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);
@rosuH rosuH merged commit d32aa63 into main Jul 6, 2026
2 checks passed
rosuH added a commit that referenced this pull request Jul 6, 2026
The bootstrap IIFE shipped since 7c95a83 was a hand-edited variant with a
structurally broken init stub: it called b._q.push(...) but only ever
initialized b._i (never b._q), so every mixpanel.init(...) threw
'TypeError: Cannot read properties of undefined (reading push') before any
tracking method (track/identify/people.set/...) could be stubbed onto the
object. Result: zero events, even with a valid SDK URL and Rocket Loader bypass.

PR #6 fixed one symptom (the a=c[0]] syntax typo from #5), but the underlying
_q/_i logic bug remained — flagged again as P1 by Codex review on #6.

Fix: replace the whole IIFE with Mixpanel's official snippet verbatim from
https://docs.mixpanel.com/docs/tracking-methods/sdks/javascript. The official
stub stubs out all methods (track, identify, people.*, ...) and records the
init call via b._i.push([...]) — matching the SDK's own contract.

Verified by executing the extracted <script> block in Node with a DOM mock:
  - mixpanel._i receives the init call
  - mixpanel.track / identify / people.set are all functions
  - No TypeError, no SyntaxError

Same snippet in site/index.html and web/index.html. data-cfasync="false"
and the existing mixpanel.init(...) config line are preserved.
rosuH added a commit that referenced this pull request Jul 6, 2026
* fix(analytics): restore Mixpanel IIFE syntax broken in PR #5

PR #5 (Rocket Loader bypass) accidentally introduced a typo in the Mixpanel
bootstrap IIFE: a[c[0]]= became a=c[0]]=, which is a JS SyntaxError
(Unexpected token ']'). The whole <script> block fails to parse, so
mixpanel.init() never runs and no events are sent — the Rocket Loader fix was
correct but got masked by this regression.

Confirmed via `node --check` on the extracted <script> block: SyntaxError on
the merged code, OK after this fix.

Reported by Codex (P1) and Copilot review on PR #5.

Only the two bytes a[ → a= are changed; nothing else.

* fix(analytics): replace corrupted Mixpanel stub with official snippet

The bootstrap IIFE shipped since 7c95a83 was a hand-edited variant with a
structurally broken init stub: it called b._q.push(...) but only ever
initialized b._i (never b._q), so every mixpanel.init(...) threw
'TypeError: Cannot read properties of undefined (reading push') before any
tracking method (track/identify/people.set/...) could be stubbed onto the
object. Result: zero events, even with a valid SDK URL and Rocket Loader bypass.

PR #6 fixed one symptom (the a=c[0]] syntax typo from #5), but the underlying
_q/_i logic bug remained — flagged again as P1 by Codex review on #6.

Fix: replace the whole IIFE with Mixpanel's official snippet verbatim from
https://docs.mixpanel.com/docs/tracking-methods/sdks/javascript. The official
stub stubs out all methods (track, identify, people.*, ...) and records the
init call via b._i.push([...]) — matching the SDK's own contract.

Verified by executing the extracted <script> block in Node with a DOM mock:
  - mixpanel._i receives the init call
  - mixpanel.track / identify / people.set are all functions
  - No TypeError, no SyntaxError

Same snippet in site/index.html and web/index.html. data-cfasync="false"
and the existing mixpanel.init(...) config line are preserved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants