mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-29 10:12:34 +00:00
feat: Setup posthog analytics (#12291)
- Replace June.so analytics with PostHog integration - Maintain existing analytics API interface for seamless migration - Remove all the June references _June.so is shutting down their service, requiring migration to an alternative analytics provider. PostHog was chosen as the replacement due to its robust feature set and similar API structure._
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { AnalyticsBrowser } from '@june-so/analytics-next';
|
||||
import posthog from 'posthog-js';
|
||||
|
||||
/**
|
||||
* AnalyticsHelper class to initialize and track user analytics
|
||||
@@ -26,10 +26,12 @@ export class AnalyticsHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
let [analytics] = await AnalyticsBrowser.load({
|
||||
writeKey: this.analyticsToken,
|
||||
posthog.init(this.analyticsToken, {
|
||||
api_host: 'https://app.posthog.com',
|
||||
capture_pageview: false,
|
||||
persistence: 'localStorage+cookie',
|
||||
});
|
||||
this.analytics = analytics;
|
||||
this.analytics = posthog;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,8 +45,7 @@ export class AnalyticsHelper {
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
this.analytics.identify(this.user.email, {
|
||||
userId: this.user.id,
|
||||
this.analytics.identify(this.user.id.toString(), {
|
||||
email: this.user.email,
|
||||
name: this.user.name,
|
||||
avatar: this.user.avatar_url,
|
||||
@@ -55,7 +56,7 @@ export class AnalyticsHelper {
|
||||
account => account.id === accountId
|
||||
);
|
||||
if (currentAccount) {
|
||||
this.analytics.group(currentAccount.id, this.user.id, {
|
||||
this.analytics.group('company', currentAccount.id.toString(), {
|
||||
name: currentAccount.name,
|
||||
});
|
||||
}
|
||||
@@ -71,12 +72,7 @@ export class AnalyticsHelper {
|
||||
if (!this.analytics) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.analytics.track({
|
||||
userId: this.user.id,
|
||||
event: eventName,
|
||||
properties,
|
||||
});
|
||||
this.analytics.capture(eventName, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,9 +85,9 @@ export class AnalyticsHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
this.analytics.page(params);
|
||||
this.analytics.capture('$pageview', params);
|
||||
}
|
||||
}
|
||||
|
||||
// This object is shared across, the init is called in app/javascript/packs/application.js
|
||||
// This object is shared across, the init is called in app/javascript/entrypoints/dashboard.js
|
||||
export default new AnalyticsHelper(window.analyticsConfig);
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import helperObject, { AnalyticsHelper } from '../';
|
||||
|
||||
vi.mock('@june-so/analytics-next', () => ({
|
||||
AnalyticsBrowser: {
|
||||
load: () => [
|
||||
{
|
||||
identify: vi.fn(),
|
||||
track: vi.fn(),
|
||||
page: vi.fn(),
|
||||
group: vi.fn(),
|
||||
},
|
||||
],
|
||||
vi.mock('posthog-js', () => ({
|
||||
default: {
|
||||
init: vi.fn(),
|
||||
identify: vi.fn(),
|
||||
capture: vi.fn(),
|
||||
group: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -26,12 +22,12 @@ describe('AnalyticsHelper', () => {
|
||||
});
|
||||
|
||||
describe('init', () => {
|
||||
it('should initialize the analytics browser with the correct token', async () => {
|
||||
it('should initialize posthog with the correct token', async () => {
|
||||
await analyticsHelper.init();
|
||||
expect(analyticsHelper.analytics).not.toBe(null);
|
||||
});
|
||||
|
||||
it('should not initialize the analytics browser if token is not provided', async () => {
|
||||
it('should not initialize posthog if token is not provided', async () => {
|
||||
analyticsHelper = new AnalyticsHelper();
|
||||
await analyticsHelper.init();
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
@@ -43,36 +39,36 @@ describe('AnalyticsHelper', () => {
|
||||
analyticsHelper.analytics = { identify: vi.fn(), group: vi.fn() };
|
||||
});
|
||||
|
||||
it('should call identify on analytics browser with correct arguments', () => {
|
||||
it('should call identify on posthog with correct arguments', () => {
|
||||
analyticsHelper.identify({
|
||||
id: '123',
|
||||
id: 123,
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar_url: 'avatar_url',
|
||||
accounts: [{ id: '1', name: 'Account 1' }],
|
||||
account_id: '1',
|
||||
accounts: [{ id: 1, name: 'Account 1' }],
|
||||
account_id: 1,
|
||||
});
|
||||
|
||||
expect(analyticsHelper.analytics.identify).toHaveBeenCalledWith(
|
||||
'test@example.com',
|
||||
{
|
||||
userId: '123',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar: 'avatar_url',
|
||||
}
|
||||
expect(analyticsHelper.analytics.identify).toHaveBeenCalledWith('123', {
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar: 'avatar_url',
|
||||
});
|
||||
expect(analyticsHelper.analytics.group).toHaveBeenCalledWith(
|
||||
'company',
|
||||
'1',
|
||||
{ name: 'Account 1' }
|
||||
);
|
||||
expect(analyticsHelper.analytics.group).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call identify on analytics browser without group', () => {
|
||||
it('should call identify on posthog without group', () => {
|
||||
analyticsHelper.identify({
|
||||
id: '123',
|
||||
id: 123,
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
avatar_url: 'avatar_url',
|
||||
accounts: [{ id: '1', name: 'Account 1' }],
|
||||
account_id: '5',
|
||||
accounts: [{ id: 1, name: 'Account 1' }],
|
||||
account_id: 5,
|
||||
});
|
||||
|
||||
expect(analyticsHelper.analytics.group).not.toHaveBeenCalled();
|
||||
@@ -87,29 +83,27 @@ describe('AnalyticsHelper', () => {
|
||||
|
||||
describe('track', () => {
|
||||
beforeEach(() => {
|
||||
analyticsHelper.analytics = { track: vi.fn() };
|
||||
analyticsHelper.user = { id: '123' };
|
||||
analyticsHelper.analytics = { capture: vi.fn() };
|
||||
analyticsHelper.user = { id: 123 };
|
||||
});
|
||||
|
||||
it('should call track on analytics browser with correct arguments', () => {
|
||||
it('should call capture on posthog with correct arguments', () => {
|
||||
analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' });
|
||||
expect(analyticsHelper.analytics.track).toHaveBeenCalledWith({
|
||||
userId: '123',
|
||||
event: 'Test Event',
|
||||
properties: { prop1: 'value1', prop2: 'value2' },
|
||||
});
|
||||
expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith(
|
||||
'Test Event',
|
||||
{ prop1: 'value1', prop2: 'value2' }
|
||||
);
|
||||
});
|
||||
|
||||
it('should call track on analytics browser with default properties', () => {
|
||||
it('should call capture on posthog with default properties', () => {
|
||||
analyticsHelper.track('Test Event');
|
||||
expect(analyticsHelper.analytics.track).toHaveBeenCalledWith({
|
||||
userId: '123',
|
||||
event: 'Test Event',
|
||||
properties: {},
|
||||
});
|
||||
expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith(
|
||||
'Test Event',
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not call track on analytics browser if analytics is not initialized', () => {
|
||||
it('should not call capture on posthog if analytics is not initialized', () => {
|
||||
analyticsHelper.analytics = null;
|
||||
analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' });
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
@@ -118,19 +112,22 @@ describe('AnalyticsHelper', () => {
|
||||
|
||||
describe('page', () => {
|
||||
beforeEach(() => {
|
||||
analyticsHelper.analytics = { page: vi.fn() };
|
||||
analyticsHelper.analytics = { capture: vi.fn() };
|
||||
});
|
||||
|
||||
it('should call the analytics.page method with the correct arguments', () => {
|
||||
it('should call the capture method for pageview with the correct arguments', () => {
|
||||
const params = {
|
||||
name: 'Test page',
|
||||
url: '/test',
|
||||
};
|
||||
analyticsHelper.page(params);
|
||||
expect(analyticsHelper.analytics.page).toHaveBeenCalledWith(params);
|
||||
expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith(
|
||||
'$pageview',
|
||||
params
|
||||
);
|
||||
});
|
||||
|
||||
it('should not call analytics.page if analytics is null', () => {
|
||||
it('should not call analytics.capture if analytics is null', () => {
|
||||
analyticsHelper.analytics = null;
|
||||
analyticsHelper.page();
|
||||
expect(analyticsHelper.analytics).toBe(null);
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
- name: ANALYTICS_TOKEN
|
||||
value:
|
||||
display_title: 'Analytics Token'
|
||||
description: 'The June.so analytics token for Chatwoot cloud'
|
||||
description: 'The PostHog analytics token for Chatwoot cloud'
|
||||
type: secret
|
||||
- name: CLEARBIT_API_KEY
|
||||
value:
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@iconify-json/material-symbols": "^1.2.10",
|
||||
"@june-so/analytics-next": "^2.0.0",
|
||||
"@lk77/vue3-color": "^3.0.6",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@rails/actioncable": "6.1.3",
|
||||
@@ -80,6 +79,7 @@
|
||||
"md5": "^2.3.0",
|
||||
"mitt": "^3.0.1",
|
||||
"opus-recorder": "^8.0.5",
|
||||
"posthog-js": "^1.260.2",
|
||||
"semver": "7.6.3",
|
||||
"snakecase-keys": "^8.0.1",
|
||||
"timezone-phone-codes": "^0.0.2",
|
||||
|
||||
1332
pnpm-lock.yaml
generated
1332
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user