Skip to content

Commit 582ab53

Browse files
committed
Added utm params in logic flow and integrated mixpanel to trace user activity
1 parent 59304c5 commit 582ab53

6 files changed

Lines changed: 102 additions & 2 deletions

File tree

src/analytics/analytics.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import httpClient from './httpClient';
2+
class Analytics {
3+
4+
public sendEvent(eventName: string, eventID:string, errorMessage?: string, diagramType?:string, userLoginState: boolean = true) {
5+
const analyticsID = getAnalyticsID();
6+
const pluginID= "google-docs-plugin";
7+
const pluginSource = 'googledocs';
8+
const payload = {
9+
analyticsID,
10+
pluginID,
11+
eventName,
12+
eventID,
13+
userLoginState,
14+
pluginSource,
15+
errorMessage,
16+
diagramType
17+
};
18+
19+
httpClient.post('/rest-api/plugins/pulse', payload).catch(error => {
20+
if (error.code !== 'ERR_NETWORK') {
21+
console.error('Failed to send analytics event:', error);
22+
}
23+
});
24+
}
25+
26+
27+
public trackLogin() {
28+
this.sendEvent('Google Docs Plugin Logged In','GOOGLE_DOCS_PLUGIN_LOGIN');
29+
}
30+
31+
public trackLogout() {
32+
this.sendEvent('Google Docs Logged Out','GOOGLE_DOCS_PLUGIN_LOGOUT', undefined, undefined, false);
33+
}
34+
35+
public trackBrowseDiagram() {
36+
this.sendEvent('Google Docs Browse Diagram','GOOGLE_DOCS_PLUGIN_BROWSE_DIAGRAM');
37+
}
38+
39+
public trackNewDiagram() {
40+
this.sendEvent('Google Docs New Diagram', 'GOOGLE_DOCS_PLUGIN_NEW_DIAGRAM');
41+
}
42+
43+
public trackEditDiagram() {
44+
this.sendEvent('Google Docs Edit Diagram', 'GOOGLE_DOCS_PLUGIN_EDIT_DIAGRAM');
45+
}
46+
47+
public trackUpdateAllDiagrams() {
48+
this.sendEvent('Google Docs Update All Diagrams', 'GOOGLE_DOCS_PLUGIN_UPDATE_ALL_DIAGRAMS');
49+
}
50+
}
51+
52+
function getAnalyticsID() {
53+
const STORAGE_KEY = 'MERMAIDCHART_ANALYTICS_ID';
54+
55+
let id = localStorage.getItem(STORAGE_KEY);
56+
if (!id) {
57+
id = crypto.randomUUID();
58+
localStorage.setItem(STORAGE_KEY, id);
59+
}
60+
return id;
61+
}
62+
63+
export default new Analytics();

src/analytics/httpClient.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';
2+
import { prodUrl } from '../config/urls';
3+
4+
const ANALYTICS_BASE_URL = prodUrl;
5+
6+
const httpClient: AxiosInstance = axios.create({
7+
baseURL: ANALYTICS_BASE_URL,
8+
headers: {
9+
'Content-Type': 'application/json',
10+
},
11+
timeout: 10000, // 10 second timeout
12+
});
13+
14+
httpClient.interceptors.response.use(
15+
(response: AxiosResponse) => response,
16+
(error: AxiosError) => {
17+
if (error.code === 'ERR_NETWORK') {
18+
console.warn('Analytics endpoint unreachable - continuing without tracking');
19+
return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config: error.config });
20+
}
21+
console.error('HTTP Client error:', error);
22+
return Promise.reject(error);
23+
}
24+
);
25+
26+
export default httpClient;

src/client/edit-diagram-dialog/components/edit-diagram-dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const EditDiagramDialog = () => {
3131
const minor = params.get('minor');
3232
if (projectID && documentID && major && minor) {
3333
const iframeUrl = buildUrl(
34-
`/app/projects/${projectID}/diagrams/${documentID}/version/v.${major}.${minor}/edit`,
34+
`/app/projects/${projectID}/diagrams/${documentID}/version/v${major}.${minor}/edit?pluginSource=googledocs`,
3535
authState.token
3636
);
3737
setDiagramsUrl(iframeUrl);

src/client/hooks/useAuth.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useCallback, useEffect, useState } from 'react';
22
import { serverFunctions } from '../utils/serverFunctions';
33
import { baseURL } from '../../config/urls';
4+
import analytics from '../../analytics/analytics';
45

56
type Status = 'idle' | 'loading' | 'success' | 'error';
67

@@ -37,6 +38,7 @@ const useAuth = () => {
3738
}, [getAuth]);
3839

3940
const signOut = async () => {
41+
analytics.trackLogout();
4042
try {
4143
await serverFunctions.resetOAuth();
4244
setTimeout(getAuth, 500);

src/client/sidebar/components/Sidebar.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { buildUrl } from '../../utils/helpers';
1414
import useAuth from '../../hooks/useAuth';
1515
import Button from '../../components/button';
1616
import { showAlertDialog } from '../../utils/alert';
17+
import analytics from '../../../analytics/analytics';
1718

1819
interface ChartImage {
1920
altDescription: string;
@@ -137,6 +138,7 @@ const Sidebar = () => {
137138
options += ',left=' + left;
138139

139140
try {
141+
analytics.trackLogin();
140142
const authUrl = await serverFunctions.getOAuthURL();
141143
const windowObjectReference = window.open(
142144
authUrl,
@@ -152,6 +154,7 @@ const Sidebar = () => {
152154
};
153155

154156
const handleDiagramsUpdate = async () => {
157+
analytics.trackUpdateAllDiagrams();
155158
try {
156159
setUpdateDiagramsState('loading');
157160
await serverFunctions.syncImages();
@@ -164,6 +167,7 @@ const Sidebar = () => {
164167
};
165168

166169
const handleSelectDiagram = async () => {
170+
analytics.trackBrowseDiagram();
167171
try {
168172
setSelectDiagramState('loading');
169173
await serverFunctions.openSelectDiagramDialog();
@@ -176,6 +180,7 @@ const Sidebar = () => {
176180
};
177181

178182
const handleCreateDiagram = async () => {
183+
analytics.trackNewDiagram();
179184
try {
180185
setCreateDiagramState('loading');
181186
await serverFunctions.openCreateDiagramDialog();
@@ -196,6 +201,7 @@ const Sidebar = () => {
196201
};
197202

198203
const handleEditDiagram = async (altDescription: string) => {
204+
analytics.trackEditDiagram();
199205
try {
200206
await serverFunctions.selectChartImage(altDescription);
201207
await serverFunctions.openEditDiagramDialog();

src/server/ui.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,10 @@ function getOAuthService() {
188188
})
189189
.setParam('response_type', 'code')
190190
.setParam('code_challenge_method', 'S256')
191-
.setParam('code_challenge', userProps.getProperty('code_challenge') ?? '');
191+
.setParam('code_challenge', userProps.getProperty('code_challenge') ?? '')
192+
.setParam('utm_source', 'google_addon')
193+
.setParam('utm_medium', 'docs')
194+
.setParam('utm_campaign', 'plugin_usage');
192195
}
193196

194197
export function getOAuthURL() {

0 commit comments

Comments
 (0)