diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 97b610c2bf..89113efe6d 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -32,6 +32,7 @@ "@backstage/config": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "react-ga4": "^2.0.0" }, "peerDependencies": { diff --git a/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.test.ts b/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.test.ts index 16db7075b3..5bae530b2b 100644 --- a/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.test.ts +++ b/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.test.ts @@ -492,4 +492,42 @@ describe('GoogleAnalytics4', () => { }); }); }); + + describe('Backward compatibility', () => { + it('fallback category for legacy context extension property', () => { + const api = GoogleAnalytics4.fromConfig(basicValidConfig); + + expect(api.captureEvent).toBeDefined(); + + api.captureEvent({ + action: 'navigate', + subject: '/', + context, + }); + + expect(fnEvent).toHaveBeenCalledWith('page_view', { + action: 'page_view', + label: '/', + category: 'App', + }); + }); + + it('prioritize new context extension id over old extension property', () => { + const api = GoogleAnalytics4.fromConfig(basicValidConfig); + + expect(api.captureEvent).toBeDefined(); + + api.captureEvent({ + action: 'navigate', + subject: '/', + context: { ...context, extensionId: 'App', extension: '' }, + }); + + expect(fnEvent).toHaveBeenCalledWith('page_view', { + action: 'page_view', + label: '/', + category: 'App', + }); + }); + }); }); diff --git a/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.ts b/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.ts index 9abf4719c6..3d2e633962 100644 --- a/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.ts +++ b/plugins/analytics-module-ga4/src/apis/implementations/AnalyticsApi/GoogleAnalytics4.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import ReactGA from 'react-ga4'; import { AnalyticsApi, @@ -21,6 +22,11 @@ import { AnalyticsEvent, IdentityApi, } from '@backstage/core-plugin-api'; +import { + AnalyticsApi as NewAnalyticsApi, + AnalyticsEvent as NewAnalyticsEvent, + AnalyticsContextValue as NewAnalyticsContextValue, +} from '@backstage/frontend-plugin-api'; import { Config } from '@backstage/config'; import { DeferredCapture } from '../../../util/DeferredCapture'; @@ -28,7 +34,7 @@ import { DeferredCapture } from '../../../util/DeferredCapture'; * Google Analytics API provider for the Backstage Analytics API. * @public */ -export class GoogleAnalytics4 implements AnalyticsApi { +export class GoogleAnalytics4 implements AnalyticsApi, NewAnalyticsApi { private readonly customUserIdTransform?: ( userEntityRef: string, ) => Promise; @@ -157,17 +163,20 @@ export class GoogleAnalytics4 implements AnalyticsApi { * applied as they should be (set on pageview, merged object on events). * @param event - AnalyticsEvent type captured */ - captureEvent(event: AnalyticsEvent) { + captureEvent(event: AnalyticsEvent | NewAnalyticsEvent) { const { context, action, subject, value, attributes } = event; const customEventData = this.setEventParameters(context, attributes); if (this.contentGroupBy) { customEventData.content_group = context[this.contentGroupBy]!; } - if (action === 'navigate' && context.extension === 'App') { + const extensionId = context.extensionId || context.extension; + const category = extensionId ? String(extensionId) : 'App'; + + if (action === 'navigate' && category === 'App') { this.capture.event( { - category: context.extension || 'App', + category, action: 'page_view', label: subject, value, @@ -183,7 +192,7 @@ export class GoogleAnalytics4 implements AnalyticsApi { this.capture.event( { - category: context.extension || 'App', + category, action, label: subject, value, @@ -199,7 +208,7 @@ export class GoogleAnalytics4 implements AnalyticsApi { * @param attributes additional analytics event attributes */ private setEventParameters( - context: AnalyticsContextValue, + context: AnalyticsContextValue | NewAnalyticsContextValue, attributes: AnalyticsEventAttributes = {}, ) { const customEventParameters: { diff --git a/yarn.lock b/yarn.lock index 79d27b5501..5f26cb9a82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4312,6 +4312,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0