diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index abf42517c..d57ad0e53 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -16,7 +16,7 @@ class DashboardController < ActionController::Base CHATWOOT_INBOX_TOKEN API_CHANNEL_NAME API_CHANNEL_THUMBNAIL - ANALYTICS_TOKEN + CLOUD_ANALYTICS_TOKEN DIRECT_UPLOADS_ENABLED MAXIMUM_FILE_UPLOAD_SIZE HCAPTCHA_SITE_KEY diff --git a/app/javascript/dashboard/helper/AnalyticsHelper/index.js b/app/javascript/dashboard/helper/AnalyticsHelper/index.js index ba3b5c7e6..e4392f473 100644 --- a/app/javascript/dashboard/helper/AnalyticsHelper/index.js +++ b/app/javascript/dashboard/helper/AnalyticsHelper/index.js @@ -1,4 +1,4 @@ -import posthog from 'posthog-js'; +import * as amplitude from '@amplitude/analytics-browser'; /** * AnalyticsHelper class to initialize and track user analytics @@ -26,12 +26,10 @@ export class AnalyticsHelper { return; } - posthog.init(this.analyticsToken, { - api_host: 'https://app.posthog.com', - capture_pageview: false, - persistence: 'localStorage+cookie', + amplitude.init(this.analyticsToken, { + defaultTracking: false, }); - this.analytics = posthog; + this.analytics = amplitude; } /** @@ -45,20 +43,26 @@ export class AnalyticsHelper { } this.user = user; - this.analytics.identify(this.user.id.toString(), { - email: this.user.email, - name: this.user.name, - avatar: this.user.avatar_url, - }); + this.analytics.setUserId(`user-${this.user.id.toString()}`); + + const identifyEvent = new amplitude.Identify(); + identifyEvent.set('email', this.user.email); + identifyEvent.set('name', this.user.name); + identifyEvent.set('avatar', this.user.avatar_url); + this.analytics.identify(identifyEvent); const { accounts, account_id: accountId } = this.user; const [currentAccount] = accounts.filter( account => account.id === accountId ); if (currentAccount) { - this.analytics.group('company', currentAccount.id.toString(), { - name: currentAccount.name, - }); + const groupId = `account-${currentAccount.id.toString()}`; + + this.analytics.setGroup('company', groupId); + + const groupIdentify = new amplitude.Identify(); + groupIdentify.set('name', currentAccount.name); + this.analytics.groupIdentify('company', groupId, groupIdentify); } } @@ -72,20 +76,21 @@ export class AnalyticsHelper { if (!this.analytics) { return; } - this.analytics.capture(eventName, properties); + this.analytics.track(eventName, properties); } /** * Track the page views * @function - * @param {Object} params - Page view properties + * @param {string} pageName - Page name + * @param {Object} [properties={}] - Page view properties */ - page(params) { + page(pageName, properties = {}) { if (!this.analytics) { return; } - this.analytics.capture('$pageview', params); + this.analytics.track('$pageview', { pageName, ...properties }); } } diff --git a/app/javascript/dashboard/helper/AnalyticsHelper/specs/helper.spec.js b/app/javascript/dashboard/helper/AnalyticsHelper/specs/helper.spec.js index dacf7a5e0..da8553779 100644 --- a/app/javascript/dashboard/helper/AnalyticsHelper/specs/helper.spec.js +++ b/app/javascript/dashboard/helper/AnalyticsHelper/specs/helper.spec.js @@ -1,12 +1,15 @@ import helperObject, { AnalyticsHelper } from '../'; -vi.mock('posthog-js', () => ({ - default: { - init: vi.fn(), - identify: vi.fn(), - capture: vi.fn(), - group: vi.fn(), - }, +vi.mock('@amplitude/analytics-browser', () => ({ + init: vi.fn(), + setUserId: vi.fn(), + identify: vi.fn(), + setGroup: vi.fn(), + groupIdentify: vi.fn(), + track: vi.fn(), + Identify: vi.fn(() => ({ + set: vi.fn(), + })), })); describe('helperObject', () => { @@ -22,12 +25,12 @@ describe('AnalyticsHelper', () => { }); describe('init', () => { - it('should initialize posthog with the correct token', async () => { + it('should initialize amplitude with the correct token', async () => { await analyticsHelper.init(); expect(analyticsHelper.analytics).not.toBe(null); }); - it('should not initialize posthog if token is not provided', async () => { + it('should not initialize amplitude if token is not provided', async () => { analyticsHelper = new AnalyticsHelper(); await analyticsHelper.init(); expect(analyticsHelper.analytics).toBe(null); @@ -36,10 +39,15 @@ describe('AnalyticsHelper', () => { describe('identify', () => { beforeEach(() => { - analyticsHelper.analytics = { identify: vi.fn(), group: vi.fn() }; + analyticsHelper.analytics = { + setUserId: vi.fn(), + identify: vi.fn(), + setGroup: vi.fn(), + groupIdentify: vi.fn(), + }; }); - it('should call identify on posthog with correct arguments', () => { + it('should call setUserId and identify on amplitude with correct arguments', () => { analyticsHelper.identify({ id: 123, email: 'test@example.com', @@ -49,19 +57,18 @@ describe('AnalyticsHelper', () => { account_id: 1, }); - 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.setUserId).toHaveBeenCalledWith( + 'user-123' ); + expect(analyticsHelper.analytics.identify).toHaveBeenCalled(); + expect(analyticsHelper.analytics.setGroup).toHaveBeenCalledWith( + 'company', + 'account-1' + ); + expect(analyticsHelper.analytics.groupIdentify).toHaveBeenCalled(); }); - it('should call identify on posthog without group', () => { + it('should call identify on amplitude without group', () => { analyticsHelper.identify({ id: 123, email: 'test@example.com', @@ -71,10 +78,10 @@ describe('AnalyticsHelper', () => { account_id: 5, }); - expect(analyticsHelper.analytics.group).not.toHaveBeenCalled(); + expect(analyticsHelper.analytics.setGroup).not.toHaveBeenCalled(); }); - it('should not call analytics.page if analytics is null', () => { + it('should not call analytics methods if analytics is null', () => { analyticsHelper.analytics = null; analyticsHelper.identify({}); expect(analyticsHelper.analytics).toBe(null); @@ -83,27 +90,27 @@ describe('AnalyticsHelper', () => { describe('track', () => { beforeEach(() => { - analyticsHelper.analytics = { capture: vi.fn() }; + analyticsHelper.analytics = { track: vi.fn() }; analyticsHelper.user = { id: 123 }; }); - it('should call capture on posthog with correct arguments', () => { + it('should call track on amplitude with correct arguments', () => { analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' }); - expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith( + expect(analyticsHelper.analytics.track).toHaveBeenCalledWith( 'Test Event', { prop1: 'value1', prop2: 'value2' } ); }); - it('should call capture on posthog with default properties', () => { + it('should call track on amplitude with default properties', () => { analyticsHelper.track('Test Event'); - expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith( + expect(analyticsHelper.analytics.track).toHaveBeenCalledWith( 'Test Event', {} ); }); - it('should not call capture on posthog if analytics is not initialized', () => { + it('should not call track on amplitude if analytics is not initialized', () => { analyticsHelper.analytics = null; analyticsHelper.track('Test Event', { prop1: 'value1', prop2: 'value2' }); expect(analyticsHelper.analytics).toBe(null); @@ -112,24 +119,25 @@ describe('AnalyticsHelper', () => { describe('page', () => { beforeEach(() => { - analyticsHelper.analytics = { capture: vi.fn() }; + analyticsHelper.analytics = { track: vi.fn() }; }); - it('should call the capture method for pageview with the correct arguments', () => { - const params = { - name: 'Test page', - url: '/test', + it('should call the track method for pageview with the correct arguments', () => { + const pageName = 'home'; + const properties = { + path: '/test', + name: 'home', }; - analyticsHelper.page(params); - expect(analyticsHelper.analytics.capture).toHaveBeenCalledWith( + analyticsHelper.page(pageName, properties); + expect(analyticsHelper.analytics.track).toHaveBeenCalledWith( '$pageview', - params + { pageName: 'home', path: '/test', name: 'home' } ); }); - it('should not call analytics.capture if analytics is null', () => { + it('should not call analytics.track if analytics is null', () => { analyticsHelper.analytics = null; - analyticsHelper.page(); + analyticsHelper.page('home'); expect(analyticsHelper.analytics).toBe(null); }); }); diff --git a/app/views/layouts/vueapp.html.erb b/app/views/layouts/vueapp.html.erb index 6cb238c6e..d97ece981 100644 --- a/app/views/layouts/vueapp.html.erb +++ b/app/views/layouts/vueapp.html.erb @@ -63,10 +63,10 @@ } window.errorLoggingConfig = '<%= ENV.fetch('SENTRY_FRONTEND_DSN', '') || ENV.fetch('SENTRY_DSN', '') %>' - <% if @global_config['ANALYTICS_TOKEN'].present? %> + <% if @global_config['CLOUD_ANALYTICS_TOKEN'].present? %> <% end %> diff --git a/config/installation_config.yml b/config/installation_config.yml index 8581deb97..567da8a59 100644 --- a/config/installation_config.yml +++ b/config/installation_config.yml @@ -225,10 +225,10 @@ - name: DEPLOYMENT_ENV value: self-hosted description: 'The deployment environment of the installation, to differentiate between Chatwoot cloud and self-hosted' -- name: ANALYTICS_TOKEN +- name: CLOUD_ANALYTICS_TOKEN value: display_title: 'Analytics Token' - description: 'The PostHog analytics token for Chatwoot cloud' + description: 'The Amplitude analytics API key for Chatwoot cloud' type: secret - name: CLEARBIT_API_KEY value: diff --git a/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb b/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb index 0ed7ee67a..87ac8f6d6 100644 --- a/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb +++ b/enterprise/app/controllers/enterprise/super_admin/app_configs_controller.rb @@ -34,9 +34,9 @@ module Enterprise::SuperAdmin::AppConfigsController end def internal_config_options - %w[CHATWOOT_INBOX_TOKEN CHATWOOT_INBOX_HMAC_KEY ANALYTICS_TOKEN CLEARBIT_API_KEY DASHBOARD_SCRIPTS INACTIVE_WHATSAPP_NUMBERS BLOCKED_EMAIL_DOMAINS + %w[CHATWOOT_INBOX_TOKEN CHATWOOT_INBOX_HMAC_KEY CLOUD_ANALYTICS_TOKEN CLEARBIT_API_KEY DASHBOARD_SCRIPTS INACTIVE_WHATSAPP_NUMBERS SKIP_INCOMING_BCC_PROCESSING CAPTAIN_CLOUD_PLAN_LIMITS ACCOUNT_SECURITY_NOTIFICATION_WEBHOOK_URL CHATWOOT_INSTANCE_ADMIN_EMAIL - OG_IMAGE_CDN_URL OG_IMAGE_CLIENT_REF CLOUDFLARE_API_KEY CLOUDFLARE_ZONE_ID + OG_IMAGE_CDN_URL OG_IMAGE_CLIENT_REF CLOUDFLARE_API_KEY CLOUDFLARE_ZONE_ID BLOCKED_EMAIL_DOMAINS OTEL_PROVIDER LANGFUSE_PUBLIC_KEY LANGFUSE_SECRET_KEY LANGFUSE_BASE_URL] end diff --git a/package.json b/package.json index 1ba064450..6d5a37b5a 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "mitt": "^3.0.1", "opus-recorder": "^8.0.5", "pinia": "^3.0.4", - "posthog-js": "^1.260.2", + "@amplitude/analytics-browser": "^2.11.10", "qrcode": "^1.5.4", "semver": "7.6.3", "snakecase-keys": "^8.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 56a7d910f..26bd3141e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,9 @@ importers: .: dependencies: + '@amplitude/analytics-browser': + specifier: ^2.11.10 + version: 2.33.1 '@breezystack/lamejs': specifier: ^1.2.7 version: 1.2.7 @@ -169,9 +172,6 @@ importers: pinia: specifier: ^3.0.4 version: 3.0.4(typescript@5.6.2)(vue@3.5.12(typescript@5.6.2)) - posthog-js: - specifier: ^1.260.2 - version: 1.260.3 qrcode: specifier: ^1.5.4 version: 1.5.4 @@ -371,6 +371,30 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@amplitude/analytics-browser@2.33.1': + resolution: {integrity: sha512-93wZjuAFJ7QdyptF82i1pezm5jKuBWITHI++XshDgpks1RstJvJ9n11Ak8MnE4L2BGQ93XDN2aVEHfmQkt0/Pw==} + + '@amplitude/analytics-connector@1.6.4': + resolution: {integrity: sha512-SpIv0IQMNIq6SH3UqFGiaZyGSc7PBZwRdq7lvP0pBxW8i4Ny+8zwI0pV+VMfMHQwWY3wdIbWw5WQphNjpdq1/Q==} + + '@amplitude/analytics-core@2.35.0': + resolution: {integrity: sha512-7RmHYELXCGu8yuO9D6lEXiqkMtiC5sePNhCWmwuP30dneDYHtH06gaYvAFH/YqOFuE6enwEEJfFYtcaPhyiqtA==} + + '@amplitude/plugin-autocapture-browser@1.18.3': + resolution: {integrity: sha512-njYque5t1QCEEe5V8Ls4yVVklTM6V7OXxBk6pqznN/hj/Pc4X8Wjy898pZ2VtbnvpagBKKzGb5B6Syl8OXiicw==} + + '@amplitude/plugin-network-capture-browser@1.7.3': + resolution: {integrity: sha512-zfWgAN7g6AigJAsgrGmlgVwydOHH6XvweBoxhU+qEvRydboiIVCDLSxuXczUsBG7kYVLWRdBK1DYoE5J7lqTGA==} + + '@amplitude/plugin-page-url-enrichment-browser@0.5.9': + resolution: {integrity: sha512-TqdELx4WrdRutCjHUFUzum/f/UjhbdTZw0UKkYFAj5gwAKDjaPEjL4waRvINOTaVLsne1A6ck4KEMfC8AKByFw==} + + '@amplitude/plugin-page-view-tracking-browser@2.6.6': + resolution: {integrity: sha512-dBcJlrdKgPzSgS3exDRRrMLqhIaOjwlIy7o8sEMn1PpMawERlbumSSdtfII6L4L67HYUPo4PY4Kp4acqSzaLvQ==} + + '@amplitude/plugin-web-vitals-browser@1.1.4': + resolution: {integrity: sha512-XQXI9OjTNSz2yi0lXw2VYMensDzzSkMCfvXNniTb1LgnHwBcQ1JWPcTqHLPFrvvNckeIdOT78vjs7yA+c1FyzA==} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -1091,9 +1115,6 @@ packages: '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} - '@posthog/core@1.0.1': - resolution: {integrity: sha512-bwXUeHe+MLgENm8+/FxEbiNocOw1Vjewmm+HEUaYQe6frq8OhZnrvtnzZU3Q3DF6N0UbAmD/q+iNfNgyx8mozg==} - '@radix-ui/colors@3.0.0': resolution: {integrity: sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==} @@ -1326,6 +1347,9 @@ packages: '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/zen-observable@0.8.3': + resolution: {integrity: sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -2450,9 +2474,6 @@ packages: fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - fflate@0.4.8: - resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} - file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3791,20 +3812,6 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - posthog-js@1.260.3: - resolution: {integrity: sha512-FCtksk0GQn22Rk9P7x7dsmAO7a2aBxPeYb2O2KXSraxR8xd2G6lUOOthVDK+qgtmuhpUZuur/mHrXEslMUEtjg==} - peerDependencies: - '@rrweb/types': 2.0.0-alpha.17 - rrweb-snapshot: 2.0.0-alpha.17 - peerDependenciesMeta: - '@rrweb/types': - optional: true - rrweb-snapshot: - optional: true - - preact@10.27.1: - resolution: {integrity: sha512-V79raXEWch/rbqoNc7nT9E4ep7lu+mI3+sBmfRD4i1M73R3WLYcCtdI0ibxGVf4eQL8ZIz2nFacqEC+rmnOORQ==} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3979,6 +3986,9 @@ packages: rust-result@1.0.0: resolution: {integrity: sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -4665,8 +4675,8 @@ packages: wavesurfer.js@7.8.6: resolution: {integrity: sha512-EDexkMwkkQBTWruhfWQRkTtvRggtKFTPuJX/oZ5wbIZEfyww9EBeLr2mtkxzA1S8TlWPx6adY5WyjOlNYNyHSg==} - web-vitals@4.2.4: - resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} + web-vitals@5.1.0: + resolution: {integrity: sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==} webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -4834,6 +4844,12 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} + zen-observable-ts@1.1.0: + resolution: {integrity: sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==} + + zen-observable@0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + snapshots: '@aashutoshrathi/word-wrap@1.2.6': {} @@ -4844,6 +4860,51 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@amplitude/analytics-browser@2.33.1': + dependencies: + '@amplitude/analytics-core': 2.35.0 + '@amplitude/plugin-autocapture-browser': 1.18.3 + '@amplitude/plugin-network-capture-browser': 1.7.3 + '@amplitude/plugin-page-url-enrichment-browser': 0.5.9 + '@amplitude/plugin-page-view-tracking-browser': 2.6.6 + '@amplitude/plugin-web-vitals-browser': 1.1.4 + tslib: 2.8.1 + + '@amplitude/analytics-connector@1.6.4': {} + + '@amplitude/analytics-core@2.35.0': + dependencies: + '@amplitude/analytics-connector': 1.6.4 + tslib: 2.8.1 + zen-observable-ts: 1.1.0 + + '@amplitude/plugin-autocapture-browser@1.18.3': + dependencies: + '@amplitude/analytics-core': 2.35.0 + rxjs: 7.8.2 + tslib: 2.8.1 + + '@amplitude/plugin-network-capture-browser@1.7.3': + dependencies: + '@amplitude/analytics-core': 2.35.0 + tslib: 2.8.1 + + '@amplitude/plugin-page-url-enrichment-browser@0.5.9': + dependencies: + '@amplitude/analytics-core': 2.35.0 + tslib: 2.8.1 + + '@amplitude/plugin-page-view-tracking-browser@2.6.6': + dependencies: + '@amplitude/analytics-core': 2.35.0 + tslib: 2.8.1 + + '@amplitude/plugin-web-vitals-browser@1.1.4': + dependencies: + '@amplitude/analytics-core': 2.35.0 + tslib: 2.8.1 + web-vitals: 5.1.0 + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.8 @@ -5626,8 +5687,6 @@ snapshots: '@polka/url@1.0.0-next.28': {} - '@posthog/core@1.0.1': {} - '@radix-ui/colors@3.0.0': {} '@rails/actioncable@6.1.3': {} @@ -5810,6 +5869,8 @@ snapshots: '@types/web-bluetooth@0.0.20': {} + '@types/zen-observable@0.8.3': {} + '@ungap/structured-clone@1.2.0': {} '@videojs/http-streaming@2.13.1(video.js@7.18.1)': @@ -7202,8 +7263,6 @@ snapshots: dependencies: reusify: 1.0.4 - fflate@0.4.8: {} - file-entry-cache@6.0.1: dependencies: flat-cache: 3.1.0 @@ -8671,16 +8730,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - posthog-js@1.260.3: - dependencies: - '@posthog/core': 1.0.1 - core-js: 3.38.1 - fflate: 0.4.8 - preact: 10.27.1 - web-vitals: 4.2.4 - - preact@10.27.1: {} - prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -8895,6 +8944,10 @@ snapshots: dependencies: individual: 2.0.0 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + sade@1.8.1: dependencies: mri: 1.2.0 @@ -9667,7 +9720,7 @@ snapshots: wavesurfer.js@7.8.6: {} - web-vitals@4.2.4: {} + web-vitals@5.1.0: {} webidl-conversions@7.0.0: {} @@ -9824,3 +9877,10 @@ snapshots: yocto-queue@0.1.0: {} yocto-queue@1.1.1: {} + + zen-observable-ts@1.1.0: + dependencies: + '@types/zen-observable': 0.8.3 + zen-observable: 0.8.15 + + zen-observable@0.8.15: {}