Browse Source

feat: starting migration from GA to Matomo for better privacy (#6398)

Co-authored-by: dwelle <luzar.david@gmail.com>
Milos Vetesnik 2 years ago
parent
commit
3030e96d62
6 changed files with 76 additions and 29 deletions
  1. 5 0
      .env.development
  2. 7 0
      .env.production
  3. 31 2
      public/index.html
  4. 30 22
      src/analytics.ts
  5. 2 0
      src/global.d.ts
  6. 1 5
      src/utils.ts

+ 5 - 0
.env.development

@@ -23,6 +23,11 @@ REACT_APP_DEV_DISABLE_LIVE_RELOAD=
 
 FAST_REFRESH=false
 
+# MATOMO
+REACT_APP_MATOMO_URL=
+REACT_APP_CDN_MATOMO_TRACKER_URL=
+REACT_APP_MATOMO_SITE_ID=
+
 #Debug flags
 
 # To enable bounding box for text containers

+ 7 - 0
.env.production

@@ -12,6 +12,13 @@ REACT_APP_WS_SERVER_URL=
 REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
 
 # production-only vars
+# GOOGLE ANALYTICS
 REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13
+# MATOMO
+REACT_APP_MATOMO_URL=https://excalidraw.matomo.cloud/
+REACT_APP_CDN_MATOMO_TRACKER_URL=//cdn.matomo.cloud/excalidraw.matomo.cloud/matomo.js
+REACT_APP_MATOMO_SITE_ID=1
+
+
 
 REACT_APP_PLUS_APP=https://app.excalidraw.com

+ 31 - 2
public/index.html

@@ -146,8 +146,10 @@
       // setting this so that libraries installation reuses this window tab.
       window.name = "_excalidraw";
     </script>
-    <% if (process.env.REACT_APP_DISABLE_TRACKING !== 'true' &&
-    process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
+    <% if (process.env.REACT_APP_DISABLE_TRACKING !== 'true') { %>
+
+    <!-- LEGACY GOOGLE ANALYTICS -->
+    <% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
     <script
       async
       src="https://www.googletagmanager.com/gtag/js?id=%REACT_APP_GOOGLE_ANALYTICS_ID%"
@@ -161,6 +163,33 @@
       gtag("config", "%REACT_APP_GOOGLE_ANALYTICS_ID%");
     </script>
     <% } %>
+    <!-- end LEGACY GOOGLE ANALYTICS -->
+
+    <!-- Matomo -->
+    <% if (process.env.REACT_APP_MATOMO_URL &&
+    process.env.REACT_APP_MATOMO_SITE_ID &&
+    process.env.REACT_APP_CDN_MATOMO_TRACKER_URL) { %>
+    <script>
+      var _paq = (window._paq = window._paq || []);
+      /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+      _paq.push(["trackPageView"]);
+      _paq.push(["enableLinkTracking"]);
+      (function () {
+        var u = "%REACT_APP_MATOMO_URL%";
+        _paq.push(["setTrackerUrl", u + "matomo.php"]);
+        _paq.push(["setSiteId", "%REACT_APP_MATOMO_SITE_ID%"]);
+        var d = document,
+          g = d.createElement("script"),
+          s = d.getElementsByTagName("script")[0];
+        g.async = true;
+        g.src = "%REACT_APP_CDN_MATOMO_TRACKER_URL%";
+        s.parentNode.insertBefore(g, s);
+      })();
+    </script>
+    <% } %>
+    <!-- end Matomo analytics -->
+
+    <% } %>
 
     <!-- FIXME: remove this when we update CRA (fix SW caching) -->
     <style>

+ 30 - 22
src/analytics.ts

@@ -1,22 +1,30 @@
-export const trackEvent =
-  typeof process !== "undefined" &&
-  process.env?.REACT_APP_GOOGLE_ANALYTICS_ID &&
-  typeof window !== "undefined" &&
-  window.gtag
-    ? (category: string, action: string, label?: string, value?: number) => {
-        try {
-          window.gtag("event", action, {
-            event_category: category,
-            event_label: label,
-            value,
-          });
-        } catch (error) {
-          console.error("error logging to ga", error);
-        }
-      }
-    : typeof process !== "undefined" && process.env?.JEST_WORKER_ID
-    ? (category: string, action: string, label?: string, value?: number) => {}
-    : (category: string, action: string, label?: string, value?: number) => {
-        // Uncomment the next line to track locally
-        // console.log("Track Event", { category, action, label, value });
-      };
+export const trackEvent = (
+  category: string,
+  action: string,
+  label?: string,
+  value?: number,
+) => {
+  try {
+    // Uncomment the next line to track locally
+    // console.log("Track Event", { category, action, label, value });
+
+    if (typeof window === "undefined" || process.env.JEST_WORKER_ID) {
+      return;
+    }
+
+    if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID && window.gtag) {
+      window.gtag("event", action, {
+        event_category: category,
+        event_label: label,
+        value,
+      });
+    }
+
+    // MATOMO event tracking _paq must be same as the one in index.html
+    if (window._paq) {
+      window._paq.push(["trackEvent", category, action, label, value]);
+    }
+  } catch (error) {
+    console.error("error during analytics", error);
+  }
+};

+ 2 - 0
src/global.d.ts

@@ -18,6 +18,8 @@ interface Window {
   EXCALIDRAW_EXPORT_SOURCE: string;
   EXCALIDRAW_THROTTLE_RENDER: boolean | undefined;
   gtag: Function;
+  _paq: any[];
+  _mtm: any[];
 }
 
 interface CanvasRenderingContext2D {

+ 1 - 5
src/utils.ts

@@ -689,11 +689,7 @@ export const arrayToMapWithIndex = <T extends { id: string }>(
     return acc;
   }, new Map<string, [element: T, index: number]>());
 
-export const isTestEnv = () =>
-  typeof process !== "undefined" && process.env?.NODE_ENV === "test";
-
-export const isProdEnv = () =>
-  typeof process !== "undefined" && process.env?.NODE_ENV === "production";
+export const isTestEnv = () => process.env.NODE_ENV === "test";
 
 export const wrapEvent = <T extends Event>(name: EVENT, nativeEvent: T) => {
   return new CustomEvent(name, {