Explorar el Código

chore: Remove tracking (#2722)

* chore: Remove tracking

* process

* rename

* remove

* prod

* Update public/index.html

Co-authored-by: David Luzar <luzar.david@gmail.com>

* Update public/index.html

* eol

* more

* stats

Co-authored-by: David Luzar <luzar.david@gmail.com>
Lipis hace 4 años
padre
commit
3aa01ad272

+ 1 - 1
.env.production

@@ -1 +1 @@
-REACT_APP_INCLUDE_GTAG=true
+REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13

+ 0 - 1
Dockerfile

@@ -5,7 +5,6 @@ WORKDIR /opt/node_app
 COPY package.json package-lock.json ./
 RUN npm i --no-optional
 
-ARG REACT_APP_INCLUDE_GTAG=false
 ARG NODE_ENV=production
 
 COPY . .

+ 0 - 64
analytics.md

@@ -1,64 +0,0 @@
-| Excalidraw              | Category | Name                               | Label                           | Value     |
-| ----------------------- | -------- | ---------------------------------- | ------------------------------- | --------- |
-| Shape / Selection       | shape    | selection, rectangle, diamond, etc | `toolbar` or `shortcut`         |
-| Text on double click    | shape    | text                               | `double-click`                  |
-| Lock selection          | shape    | lock                               | `on` or `off`                   |
-| Clear canvas            | action   | clear canvas                       |
-| Zoom in                 | action   | zoom                               | in                              | `zoom`    |
-| Zoom out                | action   | zoom                               | out                             | `zoom`    |
-| Zoom fit                | action   | zoom                               | fit                             | `zoom`    |
-| Zoom reset              | action   | zoom                               | reset                           | `zoom`    |
-| Scroll back to content  | action   | scroll to content                  |
-| Load file               | io       | load                               | `MIME type`                     |
-| Import from URL         | io       | import                             |
-| Save                    | io       | save                               |
-| Save as                 | io       | save as                            |
-| Export to backend       | io       | export                             | backend                         |
-| Export as SVG           | io       | export                             | `svg` or `clipboard-svg`        |
-| Export to PNG           | io       | export                             | `png` or `clipboard-png`        |
-| Canvas color            | change   | canvas color                       | `color`                         |
-| Background color        | change   | background color                   | `color`                         |
-| Stroke color            | change   | stroke color                       | `color`                         |
-| Stroke width            | change   | stroke                             | width                           | `width`   |
-| Stroke style            | change   | style                              | `solid` or `dashed` or `dotted` |
-| Stroke sloppiness       | change   | stroke                             | sloppiness                      | `value`   |
-| Fill                    | change   | fill                               | `value`                         |
-| Edge                    | change   | edge                               | `value`                         |
-| Opacity                 | change   | opacity                            | value                           | `opacity` |
-| Project name            | change   | title                              |
-| Theme                   | change   | theme                              | `light` or `dark`               |
-| Change language         | change   | language                           | `language`                      |
-| Send to back            | layer    | move                               | `back`                          |
-| Send backward           | layer    | move                               | `down`                          |
-| Bring to front          | layer    | move                               | `front`                         |
-| Bring forward           | layer    | move                               | `up`                            |
-| Align left              | align    | align                              | `left`                          |
-| Align right             | align    | align                              | `right`                         |
-| Align top               | align    | align                              | `top`                           |
-| Align bottom            | align    | align                              | `bottom`                        |
-| Center horizontally     | align    | horizontally                       | `center`                        |
-| Center vertically       | align    | vertically                         | `center`                        |
-| Distribute horizontally | align    | distribute                         | `horizontally`                  |
-| Distribute vertically   | align    | distribute                         | `vertically`                    |
-| Start session           | share    | session start                      |
-| Join session            | share    | session join                       |
-| Start end               | share    | session end                        |
-| Copy room link          | share    | copy link                          |
-| Go to collaborator      | share    | go to collaborator                 |
-| Change name             | share    | name                               |
-| Add to library          | library  | add                                |
-| Remove from library     | library  | remove                             |
-| Load library            | library  | load                               |
-| Save library            | library  | save                               |
-| Import library          | library  | import                             |
-| Shortcuts dialog        | dialog   | shortcuts                          |
-| Collaboration dialog    | dialog   | collaboration                      |
-| Export dialog           | dialog   | export                             |
-| Library dialog          | dialog   | library                            |
-| E2EE shield             | exit     | e2ee shield                        |
-| GitHub corner           | exit     | github                             |
-| Excalidraw blog         | exit     | blog                               |
-| Excalidraw guides       | exit     | guides                             |
-| File issues             | exit     | issues                             |
-| First load              | load     | first load                         |
-| Load from stroage       | load     | storage                            | size                            | `bytes`   |

+ 2 - 2
package.json

@@ -81,8 +81,8 @@
   "private": true,
   "scripts": {
     "build-node": "node ./scripts/build-node.js",
-    "build:app:docker": "REACT_APP_INCLUDE_GTAG=false REACT_APP_DISABLE_SENTRY=true react-scripts build",
-    "build:app": "REACT_APP_INCLUDE_GTAG=true REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build",
+    "build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build",
+    "build:app": "REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build",
     "build:version": "node ./scripts/build-version.js",
     "build": "npm run build:app && npm run build:version",
     "eject": "react-scripts eject",

+ 3 - 3
public/index.html

@@ -86,10 +86,10 @@
 
     <link rel="stylesheet" href="fonts.css" type="text/css" />
 
-    <% if (process.env.REACT_APP_INCLUDE_GTAG === 'true') { %>
+    <% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
     <script
       async
-      src="https://www.googletagmanager.com/gtag/js?id=UA-387204-13"
+      src="https://www.googletagmanager.com/gtag/js?id=%REACT_APP_GOOGLE_ANALYTICS_ID%"
     ></script>
     <script>
       window.dataLayer = window.dataLayer || [];
@@ -97,7 +97,7 @@
         dataLayer.push(arguments);
       }
       gtag("js", new Date());
-      gtag("config", "UA-387204-13");
+      gtag("config", "%REACT_APP_GOOGLE_ANALYTICS_ID%");
     </script>
     <% } %>
 

+ 0 - 2
src/actions/actionAddToLibrary.ts

@@ -3,7 +3,6 @@ import { getSelectedElements } from "../scene";
 import { getNonDeletedElements } from "../element";
 import { deepCopyElement } from "../element/newElement";
 import { Library } from "../data/library";
-import { EVENT_LIBRARY, trackEvent } from "../analytics";
 
 export const actionAddToLibrary = register({
   name: "addToLibrary",
@@ -16,7 +15,6 @@ export const actionAddToLibrary = register({
     Library.loadLibrary().then((items) => {
       Library.saveLibrary([...items, selectedElements.map(deepCopyElement)]);
     });
-    trackEvent(EVENT_LIBRARY, "add");
     return false;
   },
   contextMenuOrder: 6,

+ 6 - 13
src/actions/actionAlign.tsx

@@ -1,7 +1,5 @@
 import React from "react";
-import { KEYS } from "../keys";
-import { t } from "../i18n";
-import { register } from "./register";
+import { alignElements, Alignment } from "../align";
 import {
   AlignBottomIcon,
   AlignLeftIcon,
@@ -10,14 +8,15 @@ import {
   CenterHorizontallyIcon,
   CenterVerticallyIcon,
 } from "../components/icons";
-import { getSelectedElements, isSomeElementSelected } from "../scene";
-import { getElementMap, getNonDeletedElements } from "../element";
 import { ToolButton } from "../components/ToolButton";
+import { getElementMap, getNonDeletedElements } from "../element";
 import { ExcalidrawElement } from "../element/types";
+import { t } from "../i18n";
+import { KEYS } from "../keys";
+import { getSelectedElements, isSomeElementSelected } from "../scene";
 import { AppState } from "../types";
-import { alignElements, Alignment } from "../align";
 import { getShortcutKey } from "../utils";
-import { trackEvent, EVENT_ALIGN } from "../analytics";
+import { register } from "./register";
 
 const enableActionGroup = (
   elements: readonly ExcalidrawElement[],
@@ -44,7 +43,6 @@ const alignSelectedElements = (
 export const actionAlignTop = register({
   name: "alignTop",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "align", "top");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {
@@ -74,7 +72,6 @@ export const actionAlignTop = register({
 export const actionAlignBottom = register({
   name: "alignBottom",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "align", "bottom");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {
@@ -104,7 +101,6 @@ export const actionAlignBottom = register({
 export const actionAlignLeft = register({
   name: "alignLeft",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "align", "left");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {
@@ -134,7 +130,6 @@ export const actionAlignLeft = register({
 export const actionAlignRight = register({
   name: "alignRight",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "align", "right");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {
@@ -164,7 +159,6 @@ export const actionAlignRight = register({
 export const actionAlignVerticallyCentered = register({
   name: "alignVerticallyCentered",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "vertically", "center");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {
@@ -190,7 +184,6 @@ export const actionAlignVerticallyCentered = register({
 export const actionAlignHorizontallyCentered = register({
   name: "alignHorizontallyCentered",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "horizontally", "center");
     return {
       appState,
       elements: alignSelectedElements(elements, appState, {

+ 0 - 17
src/actions/actionCanvas.tsx

@@ -1,7 +1,5 @@
 import React from "react";
-import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics";
 import { getDefaultAppState } from "../appState";
-import colors from "../colors";
 import { ColorPicker } from "../components/ColorPicker";
 import { resetZoom, trash, zoomIn, zoomOut } from "../components/icons";
 import { ToolButton } from "../components/ToolButton";
@@ -21,15 +19,6 @@ import { register } from "./register";
 export const actionChangeViewBackgroundColor = register({
   name: "changeViewBackgroundColor",
   perform: (_, appState, value) => {
-    if (value !== appState.viewBackgroundColor) {
-      trackEvent(
-        EVENT_CHANGE,
-        "canvas color",
-        colors.canvasBackground.includes(value)
-          ? `${value} (picker ${colors.canvasBackground.indexOf(value)})`
-          : value,
-      );
-    }
     return {
       appState: { ...appState, viewBackgroundColor: value },
       commitToHistory: true,
@@ -52,7 +41,6 @@ export const actionChangeViewBackgroundColor = register({
 export const actionClearCanvas = register({
   name: "clearCanvas",
   perform: (elements, appState: AppState) => {
-    trackEvent(EVENT_ACTION, "clear canvas");
     return {
       elements: elements.map((element) =>
         newElementWith(element, { isDeleted: true }),
@@ -98,7 +86,6 @@ export const actionZoomIn = register({
       { left: appState.offsetLeft, top: appState.offsetTop },
       { x: appState.width / 2, y: appState.height / 2 },
     );
-    trackEvent(EVENT_ACTION, "zoom", "in", zoom.value * 100);
     return {
       appState: {
         ...appState,
@@ -133,7 +120,6 @@ export const actionZoomOut = register({
       { x: appState.width / 2, y: appState.height / 2 },
     );
 
-    trackEvent(EVENT_ACTION, "zoom", "out", zoom.value * 100);
     return {
       appState: {
         ...appState,
@@ -161,7 +147,6 @@ export const actionZoomOut = register({
 export const actionResetZoom = register({
   name: "resetZoom",
   perform: (_elements, appState) => {
-    trackEvent(EVENT_ACTION, "zoom", "reset", 100);
     return {
       appState: {
         ...appState,
@@ -234,12 +219,10 @@ const zoomToFitElements = (
     left: appState.offsetLeft,
     top: appState.offsetTop,
   });
-  const action = zoomToSelection ? "selection" : "fit";
 
   const [x1, y1, x2, y2] = commonBounds;
   const centerX = (x1 + x2) / 2;
   const centerY = (y1 + y2) / 2;
-  trackEvent(EVENT_ACTION, "zoom", action, newZoom.value * 100);
   return {
     appState: {
       ...appState,

+ 6 - 9
src/actions/actionDistribute.tsx

@@ -1,19 +1,18 @@
 import React from "react";
-import { CODES } from "../keys";
-import { t } from "../i18n";
-import { register } from "./register";
 import {
   DistributeHorizontallyIcon,
   DistributeVerticallyIcon,
 } from "../components/icons";
-import { getSelectedElements, isSomeElementSelected } from "../scene";
-import { getElementMap, getNonDeletedElements } from "../element";
 import { ToolButton } from "../components/ToolButton";
+import { distributeElements, Distribution } from "../disitrubte";
+import { getElementMap, getNonDeletedElements } from "../element";
 import { ExcalidrawElement } from "../element/types";
+import { t } from "../i18n";
+import { CODES } from "../keys";
+import { getSelectedElements, isSomeElementSelected } from "../scene";
 import { AppState } from "../types";
-import { distributeElements, Distribution } from "../disitrubte";
 import { getShortcutKey } from "../utils";
-import { EVENT_ALIGN, trackEvent } from "../analytics";
+import { register } from "./register";
 
 const enableActionGroup = (
   elements: readonly ExcalidrawElement[],
@@ -40,7 +39,6 @@ const distributeSelectedElements = (
 export const distributeHorizontally = register({
   name: "distributeHorizontally",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "distribute", "horizontally");
     return {
       appState,
       elements: distributeSelectedElements(elements, appState, {
@@ -69,7 +67,6 @@ export const distributeHorizontally = register({
 export const distributeVertically = register({
   name: "distributeVertically",
   perform: (elements, appState) => {
-    trackEvent(EVENT_ALIGN, "distribute", "vertically");
     return {
       appState,
       elements: distributeSelectedElements(elements, appState, {

+ 4 - 7
src/actions/actionExport.tsx

@@ -1,22 +1,21 @@
 import React from "react";
-import { EVENT_CHANGE, EVENT_IO, trackEvent } from "../analytics";
-import { load, save, saveAs } from "../components/icons";
+import { trackEvent } from "../analytics";
+import { load, questionCircle, save, saveAs } from "../components/icons";
 import { ProjectName } from "../components/ProjectName";
 import { ToolButton } from "../components/ToolButton";
+import "../components/ToolIcon.scss";
 import { Tooltip } from "../components/Tooltip";
-import { questionCircle } from "../components/icons";
 import { loadFromJSON, saveAsJSON } from "../data";
 import { t } from "../i18n";
 import useIsMobile from "../is-mobile";
 import { KEYS } from "../keys";
 import { muteFSAbortError } from "../utils";
 import { register } from "./register";
-import "../components/ToolIcon.scss";
 
 export const actionChangeProjectName = register({
   name: "changeProjectName",
   perform: (_elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "title");
+    trackEvent("change", "title");
     return { appState: { ...appState, name: value }, commitToHistory: false };
   },
   PanelComponent: ({ appState, updateData }) => (
@@ -100,7 +99,6 @@ export const actionSaveScene = register({
   perform: async (elements, appState, value) => {
     try {
       const { fileHandle } = await saveAsJSON(elements, appState);
-      trackEvent(EVENT_IO, "save");
       return { commitToHistory: false, appState: { ...appState, fileHandle } };
     } catch (error) {
       if (error?.name !== "AbortError") {
@@ -131,7 +129,6 @@ export const actionSaveAsScene = register({
         ...appState,
         fileHandle: null,
       });
-      trackEvent(EVENT_IO, "save as");
       return { commitToHistory: false, appState: { ...appState, fileHandle } };
     } catch (error) {
       if (error?.name !== "AbortError") {

+ 0 - 2
src/actions/actionMenu.tsx

@@ -7,7 +7,6 @@ import { register } from "./register";
 import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
 import { CODES, KEYS } from "../keys";
 import { HelpIcon } from "../components/HelpIcon";
-import { EVENT_DIALOG, trackEvent } from "../analytics";
 
 export const actionToggleCanvasMenu = register({
   name: "toggleCanvasMenu",
@@ -72,7 +71,6 @@ export const actionFullScreen = register({
 export const actionShortcuts = register({
   name: "toggleShortcuts",
   perform: (_elements, appState) => {
-    trackEvent(EVENT_DIALOG, "shortcuts");
     return {
       appState: {
         ...appState,

+ 3 - 5
src/actions/actionNavigate.tsx

@@ -1,16 +1,14 @@
 import React from "react";
-import { Avatar } from "../components/Avatar";
-import { register } from "./register";
 import { getClientColors, getClientInitials } from "../clients";
-import { Collaborator } from "../types";
+import { Avatar } from "../components/Avatar";
 import { centerScrollOn } from "../scene/scroll";
-import { EVENT_SHARE, trackEvent } from "../analytics";
+import { Collaborator } from "../types";
+import { register } from "./register";
 
 export const actionGoToCollaborator = register({
   name: "goToCollaborator",
   perform: (_elements, appState, value) => {
     const point = value as Collaborator["pointer"];
-    trackEvent(EVENT_SHARE, "go to collaborator");
     if (!point) {
       return { appState, commitToHistory: false };
     }

+ 39 - 73
src/actions/actionProperties.tsx

@@ -1,56 +1,53 @@
 import React from "react";
-import { getLanguage } from "../i18n";
+import { AppState } from "../../src/types";
+import { ButtonIconSelect } from "../components/ButtonIconSelect";
+import { ButtonSelect } from "../components/ButtonSelect";
+import { ColorPicker } from "../components/ColorPicker";
+import { IconPicker } from "../components/IconPicker";
 import {
+  ArrowheadArrowIcon,
+  ArrowheadBarIcon,
+  ArrowheadDotIcon,
+  ArrowheadNoneIcon,
+  EdgeRoundIcon,
+  EdgeSharpIcon,
+  FillCrossHatchIcon,
+  FillHachureIcon,
+  FillSolidIcon,
+  SloppinessArchitectIcon,
+  SloppinessArtistIcon,
+  SloppinessCartoonistIcon,
+  StrokeStyleDashedIcon,
+  StrokeStyleDottedIcon,
+  StrokeStyleSolidIcon,
+  StrokeWidthIcon,
+} from "../components/icons";
+import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE } from "../constants";
+import {
+  getNonDeletedElements,
+  isTextElement,
+  redrawTextBoundingBox,
+} from "../element";
+import { newElementWith } from "../element/mutateElement";
+import { isLinearElement, isLinearElementType } from "../element/typeChecks";
+import {
+  Arrowhead,
   ExcalidrawElement,
+  ExcalidrawLinearElement,
   ExcalidrawTextElement,
-  TextAlign,
   FontFamily,
-  ExcalidrawLinearElement,
-  Arrowhead,
+  TextAlign,
 } from "../element/types";
+import { getLanguage, t } from "../i18n";
+import { randomInteger } from "../random";
 import {
-  getCommonAttributeOfSelectedElements,
-  isSomeElementSelected,
-  getTargetElements,
   canChangeSharpness,
   canHaveArrowheads,
+  getCommonAttributeOfSelectedElements,
+  getTargetElements,
+  isSomeElementSelected,
 } from "../scene";
-import { ButtonSelect } from "../components/ButtonSelect";
-import { ButtonIconSelect } from "../components/ButtonIconSelect";
-import { IconPicker } from "../components/IconPicker";
-import {
-  isTextElement,
-  redrawTextBoundingBox,
-  getNonDeletedElements,
-} from "../element";
-import { isLinearElement, isLinearElementType } from "../element/typeChecks";
-import { ColorPicker } from "../components/ColorPicker";
-import { AppState } from "../../src/types";
-import { t } from "../i18n";
 import { register } from "./register";
-import { newElementWith } from "../element/mutateElement";
-import { DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY } from "../constants";
-import { randomInteger } from "../random";
-import {
-  FillHachureIcon,
-  FillCrossHatchIcon,
-  FillSolidIcon,
-  StrokeWidthIcon,
-  StrokeStyleSolidIcon,
-  StrokeStyleDashedIcon,
-  StrokeStyleDottedIcon,
-  EdgeSharpIcon,
-  EdgeRoundIcon,
-  SloppinessArchitectIcon,
-  SloppinessArtistIcon,
-  SloppinessCartoonistIcon,
-  ArrowheadArrowIcon,
-  ArrowheadBarIcon,
-  ArrowheadDotIcon,
-  ArrowheadNoneIcon,
-} from "../components/icons";
-import { EVENT_CHANGE, trackEvent } from "../analytics";
-import colors from "../colors";
 
 const changeProperty = (
   elements: readonly ExcalidrawElement[],
@@ -92,15 +89,6 @@ const getFormValue = function <T>(
 export const actionChangeStrokeColor = register({
   name: "changeStrokeColor",
   perform: (elements, appState, value) => {
-    if (value !== appState.currentItemStrokeColor) {
-      trackEvent(
-        EVENT_CHANGE,
-        "stroke color",
-        colors.elementStroke.includes(value)
-          ? `${value} (picker ${colors.elementStroke.indexOf(value)})`
-          : value,
-      );
-    }
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -132,16 +120,6 @@ export const actionChangeStrokeColor = register({
 export const actionChangeBackgroundColor = register({
   name: "changeBackgroundColor",
   perform: (elements, appState, value) => {
-    if (value !== appState.currentItemBackgroundColor) {
-      trackEvent(
-        EVENT_CHANGE,
-        "background color",
-        colors.elementBackground.includes(value)
-          ? `${value} (picker ${colors.elementBackground.indexOf(value)})`
-          : value,
-      );
-    }
-
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -173,7 +151,6 @@ export const actionChangeBackgroundColor = register({
 export const actionChangeFillStyle = register({
   name: "changeFillStyle",
   perform: (elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "fill", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -223,7 +200,6 @@ export const actionChangeFillStyle = register({
 export const actionChangeStrokeWidth = register({
   name: "changeStrokeWidth",
   perform: (elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "stroke", "width", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -286,7 +262,6 @@ export const actionChangeStrokeWidth = register({
 export const actionChangeSloppiness = register({
   name: "changeSloppiness",
   perform: (elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "stroke", "sloppiness", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -335,7 +310,6 @@ export const actionChangeSloppiness = register({
 export const actionChangeStrokeStyle = register({
   name: "changeStrokeStyle",
   perform: (elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "style", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -383,7 +357,6 @@ export const actionChangeStrokeStyle = register({
 export const actionChangeOpacity = register({
   name: "changeOpacity",
   perform: (elements, appState, value) => {
-    trackEvent(EVENT_CHANGE, "opacity", "value", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -580,7 +553,6 @@ export const actionChangeSharpness = register({
     const shouldUpdateForLinearElements = targetElements.length
       ? targetElements.every(isLinearElement)
       : isLinearElementType(appState.elementType);
-    trackEvent(EVENT_CHANGE, "edge", value);
     return {
       elements: changeProperty(elements, appState, (el) =>
         newElementWith(el, {
@@ -642,12 +614,6 @@ export const actionChangeArrowhead = register({
     return {
       elements: changeProperty(elements, appState, (el) => {
         if (isLinearElement(el)) {
-          trackEvent(
-            EVENT_CHANGE,
-            `arrowhead ${value.position}`,
-            value.type || "none",
-          );
-
           const { position, type } = value;
 
           if (position === "start") {

+ 5 - 15
src/analytics.ts

@@ -1,18 +1,7 @@
-export const EVENT_ACTION = "action";
-export const EVENT_ALIGN = "align";
-export const EVENT_CHANGE = "change";
-export const EVENT_DIALOG = "dialog";
-export const EVENT_EXIT = "exit";
-export const EVENT_IO = "io";
-export const EVENT_LAYER = "layer";
-export const EVENT_LIBRARY = "library";
-export const EVENT_LOAD = "load";
-export const EVENT_SHAPE = "shape";
-export const EVENT_SHARE = "share";
-export const EVENT_MAGIC = "magic";
-
 export const trackEvent =
-  typeof window !== "undefined" && window.gtag
+  process.env.REACT_APP_GOOGLE_ANALYTICS_ID &&
+  typeof window !== "undefined" &&
+  window.gtag
     ? (category: string, name: string, label?: string, value?: number) => {
         window.gtag("event", name, {
           event_category: category,
@@ -23,5 +12,6 @@ export const trackEvent =
     : typeof process !== "undefined" && process?.env?.JEST_WORKER_ID
     ? (category: string, name: string, label?: string, value?: number) => {}
     : (category: string, name: string, label?: string, value?: number) => {
-        console.info("Track Event", category, name, label, value);
+        // Uncomment the next line to track locally
+        // console.info("Track Event", category, name, label, value);
       };

+ 2 - 2
src/charts.ts

@@ -1,4 +1,4 @@
-import { EVENT_MAGIC, trackEvent } from "./analytics";
+import { trackEvent } from "./analytics";
 import colors from "./colors";
 import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, ENV } from "./constants";
 import { newElement, newLinearElement, newTextElement } from "./element";
@@ -473,7 +473,7 @@ export const renderSpreadsheet = (
   x: number,
   y: number,
 ): ChartElements => {
-  trackEvent(EVENT_MAGIC, "chart", chartType, spreadsheet.values.length);
+  trackEvent("magic", "chart", chartType, spreadsheet.values.length);
   if (chartType === "line") {
     return chartTypeLine(spreadsheet, x, y);
   }

+ 9 - 14
src/components/Actions.tsx

@@ -1,23 +1,22 @@
 import React from "react";
-import { AppState, Zoom } from "../types";
-import { ExcalidrawElement } from "../element/types";
 import { ActionManager } from "../actions/manager";
+import { getNonDeletedElements } from "../element";
+import { ExcalidrawElement } from "../element/types";
+import { t } from "../i18n";
+import useIsMobile from "../is-mobile";
 import {
-  hasBackground,
-  hasStroke,
   canChangeSharpness,
-  hasText,
   canHaveArrowheads,
   getTargetElements,
+  hasBackground,
+  hasStroke,
+  hasText,
 } from "../scene";
-import { t } from "../i18n";
 import { SHAPES } from "../shapes";
-import { ToolButton } from "./ToolButton";
+import { AppState, Zoom } from "../types";
 import { capitalizeString, isTransparent, setCursorForShape } from "../utils";
 import Stack from "./Stack";
-import useIsMobile from "../is-mobile";
-import { getNonDeletedElements } from "../element";
-import { trackEvent, EVENT_SHAPE, EVENT_DIALOG } from "../analytics";
+import { ToolButton } from "./ToolButton";
 
 export const SelectedShapeActions = ({
   appState,
@@ -181,7 +180,6 @@ export const ShapesSwitcher = ({
           aria-keyshortcuts={shortcut}
           data-testid={value}
           onChange={() => {
-            trackEvent(EVENT_SHAPE, value, "toolbar");
             setAppState({
               elementType: value,
               multiElement: null,
@@ -203,9 +201,6 @@ export const ShapesSwitcher = ({
       title={`${capitalizeString(t("toolBar.library"))} — 9`}
       aria-label={capitalizeString(t("toolBar.library"))}
       onClick={() => {
-        if (!isLibraryOpen) {
-          trackEvent(EVENT_DIALOG, "library");
-        }
         setAppState({ isLibraryOpen: !isLibraryOpen });
       }}
     />

+ 3 - 15
src/components/App.tsx

@@ -8,12 +8,7 @@ import { createRedoAction, createUndoAction } from "../actions/actionHistory";
 import { ActionManager } from "../actions/manager";
 import { actions } from "../actions/register";
 import { ActionResult } from "../actions/types";
-import {
-  EVENT_DIALOG,
-  EVENT_LIBRARY,
-  EVENT_SHAPE,
-  trackEvent,
-} from "../analytics";
+import { trackEvent } from "../analytics";
 import { getDefaultAppState } from "../appState";
 import {
   copyToClipboard,
@@ -111,7 +106,7 @@ import {
   selectGroupsForSelectedElements,
 } from "../groups";
 import { createHistory, SceneHistory } from "../history";
-import { t, getLanguage, setLanguage, languages, defaultLang } from "../i18n";
+import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n";
 import {
   CODES,
   getResizeCenterPointKey,
@@ -504,7 +499,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
         )
       ) {
         await Library.importLibrary(blob);
-        trackEvent(EVENT_LIBRARY, "import");
         this.setState({
           isLibraryOpen: true,
         });
@@ -1134,7 +1128,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 
   toggleLock = () => {
     this.setState((prevState) => {
-      trackEvent(EVENT_SHAPE, "lock", !prevState.elementLocked ? "on" : "off");
       return {
         elementLocked: !prevState.elementLocked,
         elementType: prevState.elementLocked
@@ -1158,7 +1151,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 
   toggleStats = () => {
     if (!this.state.showStats) {
-      trackEvent(EVENT_DIALOG, "stats");
+      trackEvent("dialog", "stats");
     }
     this.setState({
       showStats: !this.state.showStats,
@@ -1270,9 +1263,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     }
 
     if (event.code === CODES.NINE) {
-      if (!this.state.isLibraryOpen) {
-        trackEvent(EVENT_DIALOG, "library");
-      }
       this.setState({ isLibraryOpen: !this.state.isLibraryOpen });
     }
 
@@ -1357,7 +1347,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     ) {
       const shape = findShapeByKey(event.key);
       if (shape) {
-        trackEvent(EVENT_SHAPE, shape, "shortcut");
         this.selectShapeTool(shape);
       } else if (event.key === KEYS.Q) {
         this.toggleLock();
@@ -1741,7 +1730,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     resetCursor();
 
     if (!event[KEYS.CTRL_OR_CMD]) {
-      trackEvent(EVENT_SHAPE, "text", "double-click");
       this.startTextEditing({
         sceneX,
         sceneY,

+ 0 - 3
src/components/BackgroundPickerAndDarkModeToggle.tsx

@@ -1,6 +1,5 @@
 import React from "react";
 import { ActionManager } from "../actions/manager";
-import { EVENT_CHANGE, trackEvent } from "../analytics";
 import { AppState } from "../types";
 import { DarkModeToggle } from "./DarkModeToggle";
 
@@ -19,8 +18,6 @@ export const BackgroundPickerAndDarkModeToggle = ({
       <DarkModeToggle
         value={appState.appearance}
         onChange={(appearance) => {
-          // TODO: track the theme on the first load too
-          trackEvent(EVENT_CHANGE, "theme", appearance);
           setAppState({ appearance });
         }}
       />

+ 1 - 5
src/components/CollabButton.tsx

@@ -6,7 +6,6 @@ import useIsMobile from "../is-mobile";
 import { users } from "./icons";
 
 import "./CollabButton.scss";
-import { EVENT_DIALOG, trackEvent } from "../analytics";
 
 const CollabButton = ({
   isCollaborating,
@@ -23,10 +22,7 @@ const CollabButton = ({
         className={clsx("CollabButton", {
           "is-collaborating": isCollaborating,
         })}
-        onClick={() => {
-          trackEvent(EVENT_DIALOG, "collaboration");
-          onClick();
-        }}
+        onClick={onClick}
         icon={users}
         type="button"
         title={t("buttons.roomDialog")}

+ 0 - 2
src/components/ExportDialog.tsx

@@ -1,7 +1,6 @@
 import React, { useEffect, useRef, useState } from "react";
 import { render, unmountComponentAtNode } from "react-dom";
 import { ActionsManagerInterface } from "../actions/types";
-import { EVENT_DIALOG, trackEvent } from "../analytics";
 import { probablySupportsClipboardBlob } from "../clipboard";
 import { canvasToBlob } from "../data/blob";
 import { NonDeletedExcalidrawElement } from "../element/types";
@@ -251,7 +250,6 @@ export const ExportDialog = ({
     <>
       <ToolButton
         onClick={() => {
-          trackEvent(EVENT_DIALOG, "export");
           setModalIsShown(true);
         }}
         icon={exportFile}

+ 1 - 5
src/components/GitHubCorner.tsx

@@ -1,6 +1,5 @@
-import React from "react";
 import oc from "open-color";
-import { EVENT_EXIT, trackEvent } from "../analytics";
+import React from "react";
 
 // https://github.com/tholman/github-corners
 export const GitHubCorner = React.memo(
@@ -17,9 +16,6 @@ export const GitHubCorner = React.memo(
         target="_blank"
         rel="noopener noreferrer"
         aria-label="GitHub repository"
-        onClick={() => {
-          trackEvent(EVENT_EXIT, "github");
-        }}
       >
         <path
           d="M0 0l115 115h15l12 27 108 108V0z"

+ 29 - 51
src/components/LayerUI.tsx

@@ -1,56 +1,46 @@
+import clsx from "clsx";
 import React, {
-  useRef,
-  useState,
   RefObject,
-  useEffect,
   useCallback,
+  useEffect,
+  useRef,
+  useState,
 } from "react";
-import { showSelectedShapeActions } from "../element";
-import { calculateScrollCenter, getSelectedElements } from "../scene";
+import { ActionManager } from "../actions/manager";
+import { CLASSES } from "../constants";
 import { exportCanvas } from "../data";
-
-import { AppState, LibraryItems, LibraryItem } from "../types";
+import { importLibraryFromJSON, saveLibraryAsJSON } from "../data/json";
+import { Library } from "../data/library";
+import { showSelectedShapeActions } from "../element";
 import { NonDeletedExcalidrawElement } from "../element/types";
-
-import { ActionManager } from "../actions/manager";
-import { Island } from "./Island";
-import Stack from "./Stack";
-import { FixedSideContainer } from "./FixedSideContainer";
-import { UserList } from "./UserList";
-import { LockIcon } from "./LockIcon";
-import { ExportDialog, ExportCB } from "./ExportDialog";
 import { Language, t } from "../i18n";
-import { HintViewer } from "./HintViewer";
 import useIsMobile from "../is-mobile";
-
+import { calculateScrollCenter, getSelectedElements } from "../scene";
 import { ExportType } from "../scene/types";
-import { MobileMenu } from "./MobileMenu";
-import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
-import { Section } from "./Section";
+import { AppState, LibraryItem, LibraryItems } from "../types";
+import { muteFSAbortError } from "../utils";
+import { SelectedShapeActions, ShapesSwitcher, ZoomActions } from "./Actions";
+import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
 import CollabButton from "./CollabButton";
 import { ErrorDialog } from "./ErrorDialog";
-import { ShortcutsDialog } from "./ShortcutsDialog";
-import { LoadingMessage } from "./LoadingMessage";
-import { CLASSES } from "../constants";
-import { shield, exportFile, load } from "./icons";
+import { ExportCB, ExportDialog } from "./ExportDialog";
+import { FixedSideContainer } from "./FixedSideContainer";
 import { GitHubCorner } from "./GitHubCorner";
-import { Tooltip } from "./Tooltip";
-
+import { HintViewer } from "./HintViewer";
+import { exportFile, load, shield } from "./icons";
+import { Island } from "./Island";
 import "./LayerUI.scss";
 import { LibraryUnit } from "./LibraryUnit";
-import { ToolButton } from "./ToolButton";
-import { saveLibraryAsJSON, importLibraryFromJSON } from "../data/json";
-import { muteFSAbortError } from "../utils";
-import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
-import clsx from "clsx";
-import { Library } from "../data/library";
-import {
-  EVENT_ACTION,
-  EVENT_EXIT,
-  EVENT_LIBRARY,
-  trackEvent,
-} from "../analytics";
+import { LoadingMessage } from "./LoadingMessage";
+import { LockIcon } from "./LockIcon";
+import { MobileMenu } from "./MobileMenu";
 import { PasteChartDialog } from "./PasteChartDialog";
+import { Section } from "./Section";
+import { ShortcutsDialog } from "./ShortcutsDialog";
+import Stack from "./Stack";
+import { ToolButton } from "./ToolButton";
+import { Tooltip } from "./Tooltip";
+import { UserList } from "./UserList";
 
 interface LayerUIProps {
   actionManager: ActionManager;
@@ -159,13 +149,7 @@ const LibraryMenuItems = ({
         }}
       />
 
-      <a
-        href="https://libraries.excalidraw.com"
-        target="_excalidraw_libraries"
-        onClick={() => {
-          trackEvent(EVENT_EXIT, "libraries");
-        }}
-      >
+      <a href="https://libraries.excalidraw.com" target="_excalidraw_libraries">
         {t("labels.libraries")}
       </a>
     </div>,
@@ -267,7 +251,6 @@ const LibraryMenu = ({
     const items = await Library.loadLibrary();
     const nextItems = items.filter((_, index) => index !== indexToRemove);
     Library.saveLibrary(nextItems);
-    trackEvent(EVENT_LIBRARY, "remove");
     setLibraryItems(nextItems);
   }, []);
 
@@ -276,7 +259,6 @@ const LibraryMenu = ({
       const items = await Library.loadLibrary();
       const nextItems = [...items, elements];
       onAddToLibrary();
-      trackEvent(EVENT_LIBRARY, "add");
       Library.saveLibrary(nextItems);
       setLibraryItems(nextItems);
     },
@@ -328,9 +310,6 @@ const LayerUI = ({
       href="https://blog.excalidraw.com/end-to-end-encryption/"
       target="_blank"
       rel="noopener noreferrer"
-      onClick={() => {
-        trackEvent(EVENT_EXIT, "e2ee shield");
-      }}
     >
       <Tooltip label={t("encrypted.tooltip")} position="above" long={true}>
         {shield}
@@ -567,7 +546,6 @@ const LayerUI = ({
         <button
           className="scroll-back-to-content"
           onClick={() => {
-            trackEvent(EVENT_ACTION, "scroll to content");
             setAppState({
               ...calculateScrollCenter(elements, appState, canvas),
             });

+ 0 - 2
src/components/MobileMenu.tsx

@@ -16,7 +16,6 @@ import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars";
 import { LockIcon } from "./LockIcon";
 import { UserList } from "./UserList";
 import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
-import { EVENT_ACTION, trackEvent } from "../analytics";
 
 type MobileMenuProps = {
   appState: AppState;
@@ -149,7 +148,6 @@ export const MobileMenu = ({
             <button
               className="scroll-back-to-content"
               onClick={() => {
-                trackEvent(EVENT_ACTION, "scroll to content");
                 setAppState({
                   ...calculateScrollCenter(elements, appState, canvas),
                 });

+ 0 - 10
src/components/ShortcutsDialog.tsx

@@ -4,7 +4,6 @@ import { isDarwin } from "../keys";
 import { Dialog } from "./Dialog";
 import { getShortcutKey } from "../utils";
 import "./ShortcutsDialog.scss";
-import { EVENT_EXIT, trackEvent } from "../analytics";
 
 const Columns = (props: { children: React.ReactNode }) => (
   <div
@@ -92,9 +91,6 @@ const Footer = () => (
       href="https://blog.excalidraw.com"
       target="_blank"
       rel="noopener noreferrer"
-      onClick={() => {
-        trackEvent(EVENT_EXIT, "blog");
-      }}
     >
       {t("shortcutsDialog.blog")}
     </a>
@@ -102,9 +98,6 @@ const Footer = () => (
       href="https://howto.excalidraw.com"
       target="_blank"
       rel="noopener noreferrer"
-      onClick={() => {
-        trackEvent(EVENT_EXIT, "guides");
-      }}
     >
       {t("shortcutsDialog.howto")}
     </a>
@@ -112,9 +105,6 @@ const Footer = () => (
       href="https://github.com/excalidraw/excalidraw/issues"
       target="_blank"
       rel="noopener noreferrer"
-      onClick={() => {
-        trackEvent(EVENT_EXIT, "issues");
-      }}
     >
       {t("shortcutsDialog.github")}
     </a>

+ 0 - 2
src/data/blob.ts

@@ -1,4 +1,3 @@
-import { EVENT_IO, trackEvent } from "../analytics";
 import { cleanAppStateForExport } from "../appState";
 import { MIME_TYPES } from "../constants";
 import { clearElementsForExport } from "../element";
@@ -111,7 +110,6 @@ export const loadFromBlob = async (
       localAppState,
     );
 
-    trackEvent(EVENT_IO, "load", getMimeType(blob));
     return result;
   } catch (error) {
     console.error(error.message);

+ 1 - 6
src/data/index.ts

@@ -1,5 +1,4 @@
 import { fileSave } from "browser-nativefs";
-import { EVENT_IO, trackEvent } from "../analytics";
 import {
   copyCanvasToClipboardAsPng,
   copyTextToSystemClipboard,
@@ -8,8 +7,8 @@ import { NonDeletedExcalidrawElement } from "../element/types";
 import { t } from "../i18n";
 import { exportToCanvas, exportToSvg } from "../scene/export";
 import { ExportType } from "../scene/types";
-import { canvasToBlob } from "./blob";
 import { AppState } from "../types";
+import { canvasToBlob } from "./blob";
 import { serializeAsJSON } from "./json";
 
 export { loadFromBlob } from "./blob";
@@ -60,10 +59,8 @@ export const exportCanvas = async (
         fileName: `${name}.svg`,
         extensions: [".svg"],
       });
-      trackEvent(EVENT_IO, "export", "svg");
       return;
     } else if (type === "clipboard-svg") {
-      trackEvent(EVENT_IO, "export", "clipboard-svg");
       copyTextToSystemClipboard(tempSvg.outerHTML);
       return;
     }
@@ -95,11 +92,9 @@ export const exportCanvas = async (
       fileName,
       extensions: [".png"],
     });
-    trackEvent(EVENT_IO, "export", "png");
   } else if (type === "clipboard") {
     try {
       await copyCanvasToClipboardAsPng(tempCanvas);
-      trackEvent(EVENT_IO, "export", "clipboard-png");
     } catch (error) {
       if (error.name === "CANVAS_POSSIBLY_TOO_BIG") {
         throw error;

+ 4 - 8
src/data/json.ts

@@ -1,13 +1,11 @@
+import { fileOpen, fileSave } from "browser-nativefs";
+import { cleanAppStateForExport } from "../appState";
+import { MIME_TYPES } from "../constants";
+import { clearElementsForExport } from "../element";
 import { ExcalidrawElement } from "../element/types";
 import { AppState } from "../types";
-import { cleanAppStateForExport } from "../appState";
-
-import { fileOpen, fileSave } from "browser-nativefs";
 import { loadFromBlob } from "./blob";
 import { Library } from "./library";
-import { MIME_TYPES } from "../constants";
-import { clearElementsForExport } from "../element";
-import { EVENT_LIBRARY, trackEvent } from "../analytics";
 
 export const serializeAsJSON = (
   elements: readonly ExcalidrawElement[],
@@ -84,7 +82,6 @@ export const saveLibraryAsJSON = async () => {
     description: "Excalidraw library file",
     extensions: [".excalidrawlib"],
   });
-  trackEvent(EVENT_LIBRARY, "save");
 };
 
 export const importLibraryFromJSON = async () => {
@@ -93,6 +90,5 @@ export const importLibraryFromJSON = async () => {
     extensions: [".json", ".excalidrawlib"],
     mimeTypes: ["application/json"],
   });
-  trackEvent(EVENT_LIBRARY, "load");
   Library.importLibrary(blob);
 };

+ 19 - 25
src/excalidraw-app/collab/CollabWrapper.tsx

@@ -1,40 +1,36 @@
-import React, { PureComponent } from "react";
 import throttle from "lodash.throttle";
-
+import React, { PureComponent } from "react";
+import { ExcalidrawImperativeAPI } from "../../components/App";
+import { ErrorDialog } from "../../components/ErrorDialog";
 import { APP_NAME, ENV, EVENT } from "../../constants";
-
+import { ImportedDataState } from "../../data/types";
+import { ExcalidrawElement } from "../../element/types";
+import {
+  getSceneVersion,
+  getSyncableElements,
+} from "../../packages/excalidraw/index";
+import { AppState, Collaborator, Gesture } from "../../types";
+import { resolvablePromise, withBatchedUpdates } from "../../utils";
+import {
+  INITIAL_SCENE_UPDATE_TIMEOUT,
+  SCENE,
+  SYNC_FULL_SCENE_INTERVAL_MS,
+} from "../app_constants";
 import {
   decryptAESGEM,
-  SocketUpdateDataSource,
-  getCollaborationLinkData,
   generateCollaborationLink,
+  getCollaborationLinkData,
+  SocketUpdateDataSource,
   SOCKET_SERVER,
 } from "../data";
 import { isSavedToFirebase, saveToFirebase } from "../data/firebase";
-
-import Portal from "./Portal";
-import { AppState, Collaborator, Gesture } from "../../types";
-import { ExcalidrawElement } from "../../element/types";
 import {
   importUsernameFromLocalStorage,
   saveUsernameToLocalStorage,
   STORAGE_KEYS,
 } from "../data/localStorage";
-import { resolvablePromise, withBatchedUpdates } from "../../utils";
-import {
-  getSceneVersion,
-  getSyncableElements,
-} from "../../packages/excalidraw/index";
+import Portal from "./Portal";
 import RoomDialog from "./RoomDialog";
-import { ErrorDialog } from "../../components/ErrorDialog";
-import { ImportedDataState } from "../../data/types";
-import { ExcalidrawImperativeAPI } from "../../components/App";
-import {
-  INITIAL_SCENE_UPDATE_TIMEOUT,
-  SCENE,
-  SYNC_FULL_SCENE_INTERVAL_MS,
-} from "../app_constants";
-import { EVENT_SHARE, trackEvent } from "../../analytics";
 
 interface CollabState {
   isCollaborating: boolean;
@@ -168,7 +164,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
       elements,
       commitToHistory: true,
     });
-    trackEvent(EVENT_SHARE, "session start");
     return this.initializeSocketClient();
   };
 
@@ -176,7 +171,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
     this.saveCollabRoomToFirebase();
     window.history.pushState({}, APP_NAME, window.location.origin);
     this.destroySocketClient();
-    trackEvent(EVENT_SHARE, "session end");
   };
 
   private destroySocketClient = () => {

+ 3 - 7
src/excalidraw-app/collab/RoomDialog.tsx

@@ -1,12 +1,10 @@
 import React, { useRef } from "react";
-import { t } from "../../i18n";
-import { Dialog } from "../../components/Dialog";
 import { copyTextToSystemClipboard } from "../../clipboard";
-import { ToolButton } from "../../components/ToolButton";
+import { Dialog } from "../../components/Dialog";
 import { clipboard, start, stop } from "../../components/icons";
-
+import { ToolButton } from "../../components/ToolButton";
+import { t } from "../../i18n";
 import "./RoomDialog.scss";
-import { EVENT_SHARE, trackEvent } from "../../analytics";
 
 const RoomDialog = ({
   handleClose,
@@ -30,7 +28,6 @@ const RoomDialog = ({
   const copyRoomLink = async () => {
     try {
       await copyTextToSystemClipboard(activeRoomLink);
-      trackEvent(EVENT_SHARE, "copy link");
     } catch (error) {
       setErrorMessage(error.message);
     }
@@ -95,7 +92,6 @@ const RoomDialog = ({
                 value={username || ""}
                 className="RoomDialog-username TextInput"
                 onChange={(event) => onUsernameChange(event.target.value)}
-                onBlur={() => trackEvent(EVENT_SHARE, "name")}
                 onKeyPress={(event) => event.key === "Enter" && handleClose()}
               />
             </div>

+ 4 - 7
src/excalidraw-app/data/index.ts

@@ -1,10 +1,9 @@
-import { t } from "../../i18n";
+import { serializeAsJSON } from "../../data/json";
+import { restore } from "../../data/restore";
+import { ImportedDataState } from "../../data/types";
 import { ExcalidrawElement } from "../../element/types";
+import { t } from "../../i18n";
 import { AppState } from "../../types";
-import { ImportedDataState } from "../../data/types";
-import { restore } from "../../data/restore";
-import { EVENT_ACTION, EVENT_IO, trackEvent } from "../../analytics";
-import { serializeAsJSON } from "../../data/json";
 
 const byteToHex = (byte: number): string => `0${byte.toString(16)}`.slice(-2);
 
@@ -192,7 +191,6 @@ const importFromBackend = async (
       data = await response.json();
     }
 
-    trackEvent(EVENT_ACTION, "import");
     return {
       elements: data.elements || null,
       appState: data.appState || null,
@@ -276,7 +274,6 @@ export const exportToBackend = async (
       url.hash = `json=${json.id},${exportedKey.k!}`;
       const urlString = url.toString();
       window.prompt(`🔒${t("alerts.uploadedSecurly")}`, urlString);
-      trackEvent(EVENT_IO, "export", "backend");
     } else if (json.error_class === "RequestTooLargeError") {
       window.alert(t("alerts.couldNotCreateShareableLinkTooBig"));
     } else {

+ 23 - 37
src/excalidraw-app/index.tsx

@@ -1,46 +1,39 @@
+import LanguageDetector from "i18next-browser-languagedetector";
 import React, {
-  useState,
-  useLayoutEffect,
+  useCallback,
   useEffect,
+  useLayoutEffect,
   useRef,
-  useCallback,
+  useState,
 } from "react";
-import LanguageDetector from "i18next-browser-languagedetector";
-
+import { getDefaultAppState } from "../appState";
+import { ExcalidrawImperativeAPI } from "../components/App";
+import { ErrorDialog } from "../components/ErrorDialog";
+import { TopErrorBoundary } from "../components/TopErrorBoundary";
+import { APP_NAME, EVENT, TITLE_TIMEOUT } from "../constants";
+import { ImportedDataState } from "../data/types";
+import {
+  ExcalidrawElement,
+  NonDeletedExcalidrawElement,
+} from "../element/types";
+import { Language, t } from "../i18n";
 import Excalidraw, {
-  languages,
   defaultLang,
+  languages,
 } from "../packages/excalidraw/index";
-
+import { AppState, ExcalidrawAPIRefValue } from "../types";
+import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
+import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
+import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
+import { LanguageList } from "./components/LanguageList";
+import { exportToBackend, getCollaborationLinkData, loadScene } from "./data";
+import { loadFromFirebase } from "./data/firebase";
 import {
-  getTotalStorageSize,
   importFromLocalStorage,
   saveToLocalStorage,
   STORAGE_KEYS,
 } from "./data/localStorage";
 
-import { ImportedDataState } from "../data/types";
-import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
-import { TopErrorBoundary } from "../components/TopErrorBoundary";
-import { Language, t } from "../i18n";
-import { exportToBackend, loadScene } from "./data";
-import { getCollaborationLinkData } from "./data";
-import { EVENT } from "../constants";
-import { loadFromFirebase } from "./data/firebase";
-import { ExcalidrawImperativeAPI } from "../components/App";
-import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
-import { AppState, ExcalidrawAPIRefValue } from "../types";
-import {
-  ExcalidrawElement,
-  NonDeletedExcalidrawElement,
-} from "../element/types";
-import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
-import { EVENT_LOAD, EVENT_SHARE, trackEvent } from "../analytics";
-import { ErrorDialog } from "../components/ErrorDialog";
-import { getDefaultAppState } from "../appState";
-import { APP_NAME, TITLE_TIMEOUT } from "../constants";
-import { LanguageList } from "./components/LanguageList";
-
 const languageDetector = new LanguageDetector();
 languageDetector.init({
   languageUtils: {
@@ -163,7 +156,6 @@ const initializeScene = async (opts: {
     // into the remote scene
     opts.resetScene();
     const scenePromise = opts.initializeSocketClient();
-    trackEvent(EVENT_SHARE, "session join");
 
     try {
       const [, roomId, roomKey] = getCollaborationLinkData(
@@ -231,12 +223,6 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
   const { collab } = props;
 
   useEffect(() => {
-    const storageSize = getTotalStorageSize();
-    if (storageSize) {
-      trackEvent(EVENT_LOAD, "storage", "size", storageSize);
-    } else {
-      trackEvent(EVENT_LOAD, "first time");
-    }
     excalidrawRef.current!.readyPromise.then((excalidrawApi) => {
       initializeScene({
         resetScene: excalidrawApi.resetScene,

+ 0 - 3
src/i18n.ts

@@ -1,5 +1,3 @@
-import { EVENT_CHANGE, trackEvent } from "./analytics";
-
 import fallbackLangData from "./locales/en.json";
 import percentages from "./locales/percentages.json";
 
@@ -67,7 +65,6 @@ export const setLanguage = async (lang: Language) => {
   currentLangData = await import(
     /* webpackChunkName: "i18n-[request]" */ `./locales/${currentLang.code}.json`
   );
-  trackEvent(EVENT_CHANGE, "language", currentLang.code);
 };
 
 export const setLanguageFirstTime = async (lang: Language) => {

+ 2 - 5
src/zindex.ts

@@ -1,8 +1,7 @@
-import { AppState } from "./types";
 import { ExcalidrawElement } from "./element/types";
 import { getElementsInGroup } from "./groups";
-import { findLastIndex, findIndex } from "./utils";
-import { trackEvent, EVENT_LAYER } from "./analytics";
+import { AppState } from "./types";
+import { findIndex, findLastIndex } from "./utils";
 
 /**
  * Returns indices of elements to move based on selected elements.
@@ -176,7 +175,6 @@ const shiftElements = (
           ];
   });
 
-  trackEvent(EVENT_LAYER, "move", direction === "left" ? "down" : "up");
   return elements;
 };
 
@@ -234,7 +232,6 @@ const shiftElementsToEnd = (
   const leadingElements = elements.slice(0, leadingIndex);
   const trailingElements = elements.slice(trailingIndex + 1);
 
-  trackEvent(EVENT_LAYER, "move", direction === "left" ? "back" : "front");
   return direction === "left"
     ? [
         ...leadingElements,