mixpanel / mixpanel-js

Official Mixpanel JavaScript Client Library
https://mixpanel.com/help/reference/javascript
Other
884 stars 308 forks source link

Fetch adapter #304

Open AvivonCtrl opened 3 years ago

AvivonCtrl commented 3 years ago

Fetch instead of XHR for ServiceWorker compatibility

gmuresan commented 2 years ago

It looks like mixpanel no longer works in service workers for v3 chrome extensions. XHR has been deprecated/removed and fetch is now required. Are there any plan to migrate to fetch, or is there a workaround for service workers?

juanfer0002 commented 1 year ago

Does anyone have an update about this?

juanfer0002 commented 1 year ago

For whoever came here looking for answers, and found none, feel free to use this code.

I implemented fetch provisionally, while there's an official answer. ~I tested in development, and it is working so far.~

lukafilipov commented 1 year ago

Thank you @juanfer0002 for adding this! It's funny how the library just silently stops working with manifest v3. @tdumitrescu any idea if/when the PR juanfer created will be reviewed and merged?

juanfer0002 commented 1 year ago

@lukafilipov Since you're using this with the manifest v3, I have to warn you to be extremely careful when reporting to Mixpanel as service workers get shutdown by Chrome every five minutes.

This means that if you have identified a user, all events will be associated to them, but after 5m this identification will be lost, making every event not being correctly associated.

We had to implement a system to handle this situation, you may end up in a similar one.

lukafilipov commented 1 year ago

@juanfer0002 Got it, thanks for the heads up! And thanks again for the fix, I've tested it and it just works out of the box. I have referenced your branch directly from package.json like this: "mixpanel-browser": "juanfer0002/mixpanel-js-mv3#fetch-support-for-mv3-extensions",

spookyuser commented 1 year ago

@juanfer0002 I love you

aamirv commented 1 year ago

Thank you for working on this @juanfer0002. I am wondering if you have encountered these issues (happy to talk privately -what's the best way to do that?): 1) you mentioned that this can get running with a service worker, but it will shut down. YES, and that causes Mixpanel to see the result as different users as a result, like you said. So I thought the best practice would be to send a message back to background.js and talk to mixpanel there. Is that right? 2) related to this idea - how are you getting it into background.js? I see references to document and window, so that doesn't work.

I get this error right now: "Uncaught TypeError: Cannot set property navigator of # which has only a getter". I can comment out the line, but not sure what that is really doing.

Did you consider shifting to the HTTP API? I'm wondering if using mixpanel is worth it.

For those working on Chrome extensions.... how are you doing user tracking to learn how they are using product?

(I kind of doubt this will get merged into the main - is that right @tdumitrescu or anyone at mixpanel?)

spookyuser commented 1 year ago

Take a look at this class @aamirv it helped me a lot, I don't think you have to run it in the background but idk, on plasmo I just made this class and imported it and everything's working so might be running in the background actually.

juanfer0002 commented 1 year ago

@aamirv You can just import files in the background js with normal JS syntax, and then use it as an object. LMK if you need a more precise example, I am responding from my phone.

Regarding the other issue, when the SW shuts down, be aware that the callbacks and events are still being fired by Chrome when the port closes, in such a case I Just retry the connection with the service worker.

rahulbansal16 commented 1 year ago

"mixpanel-browser": "juanfer0002/mixpanel-js-mv3#fetch-support-for-mv3-extensions",

so just updating the package.json file will work? No other code change require?

gigabrain-kabir commented 1 year ago

Is this expected to be added to a mixpanel-js release?

neecto commented 1 year ago

any updates on this? It's tagged as "enhancement" but it's really a bug that makes mixpanel-browser unusable in chrome extensions

NorbertBodziony commented 6 months ago

Seems like real issue right now

Kitenite commented 5 months ago

Bump, this is still an issue in V3

kyranjamie commented 5 months ago

Very limiting for Web Extension users of Mixpanel.

revmischa commented 5 months ago

I need to use this in a chrome extension and I'm getting an error unless I use juanfer0002:fetch-support-for-mv3-extensions

doc-han commented 5 months ago

Want to use mixpanel for your extension? The easiest way is to write your own code.

Reasons

  1. Mixpanel-js uses a synchronous storage. You lack that in extension service worker.
  2. Mixpanel-js depends on some DOM api's you don't have access to in the service worker.
  3. Mixpanel-js doesn't support asynchronous init which you need because of [1]
  4. Mixpanel-js uses xhr instead of fetch? Sorry you only have fetch in the extension service worker

Solution

Note: Doesn't support batch processing! A simple one file drop replacement. You can edit anyhow you want! No need to install any package into your extension.

Supports init, identify, reset and track. All these functions are asynchronous and uses chrome.storage.local for $device_id and $user_id storage Below is the GIST https://gist.github.com/doc-han/6c998058744eebafc43c132bdc28bd00

Usage

The typescript code in the GIST returns an object called tracker.

Hence, all you do is use that object whenever you need. Example

// inside an extension service worker
import tracker from "./mixpanel-chrome" // importing from the gist file copy-and-pasted

// initializing mixpanel
tracker.init("<mixpanel-project-id>")

chrome.runtime.onInstalled.addListener((details) => {
    // tracking extension install
    tracker.track("install", {
        extensionVersion: chrome.runtime.getManifest().version
    })
})

function signUp(){
    const user = getSignUpUser(); // gets signed up user
    tracker.identify(user.uid); // mixpanel identify
}

function logout(){
    tracker.reset(); // mixpanel user reset on logout
}

Visit the Gist Danke!

spookyuser commented 5 months ago

I disagree if you use a patch like this in pnpm

diff --git a/dist/mixpanel.cjs.js b/dist/mixpanel.cjs.js
index 1aa8b28066511a67802cb14afd820e0d76c446b3..5a0be18ca9ec10ef3a22bbcbe7ece168b01b3aa5 100644
--- a/dist/mixpanel.cjs.js
+++ b/dist/mixpanel.cjs.js
@@ -1,3 +1,5 @@
+import XMLHttpRequest from 'xhr-shim';
+
 'use strict';

 var Config = {
@@ -3204,7 +3206,11 @@ MixpanelPeople.prototype.set = addOptOutCheckMixpanelPeople(function(prop, to, c
     }
     // make sure that the referrer info has been updated and saved
     if (this._get_config('save_referrer')) {
-        this._mixpanel['persistence'].update_referrer_info(document.referrer);
+        try{
+            this._mixpanel['persistence'].update_referrer_info(document.referrer);
+        } catch {
+            console.warn("Failed to update referrer info")
+        }
     }

     // update $set object with default people properties
@@ -4129,7 +4135,7 @@ var NOOP_FUNC = function() {};
  */
 // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
 // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials
-var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
+var USE_XHR = true

 // IE<10 does not support cross-origin XHR's but script tags
 // with defer won't block window.onload; ENQUEUE_REQUESTS
diff --git a/package.json b/package.json
index 0141403fb5b537a8649aa0a1ac6df675a46965d1..8db641b7f5bc28f1eecacb94ac42bfb1555afa79 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,9 @@
     "url": "https://github.com/mixpanel/mixpanel-js/issues"
   },
   "homepage": "https://github.com/mixpanel/mixpanel-js",
+  "dependencies": {
+    "xhr-shim": "0.1.3"
+  },
   "devDependencies": {
     "babel": "6.5.2",
     "babel-core": "6.7.2",

which adds xhr-shim to mixpanel it works with the most recent versions in chrome-mv3

revmischa commented 4 months ago

I'm using @doc-han's nice mixpanel client in my extension. I have some mixpanel shared code between the webapp and extension so I instruct webpack to swap out mixpanel-browser for the extension version behind the scenes when building the extension:

resolve: {
    alias: {
      // use chrome extension version of mixpanel client
      "mixpanel-browser": resolve(webpackExtSrcDir, "api", "mixpanelExtension.ts"),
    },
  },
brloman commented 1 month ago

Did anybody else face the error 'document undefined' when trying to load Mixpanel in an MV3 extension?

The code part that is causing the issue is mixpanel.cjs.js line 11079.

![Uploading Screenshot 2024-08-02 at 09.52.28.png…]() ![Uploading Screenshot 2024-08-02 at 09.52.20.png…]()