From fb9b05b76465427107aef9e80d6e58ecb371ac35 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Wed, 2 Jul 2025 10:52:01 -0400 Subject: [PATCH] Add preview specific UTM parameters (#32509) Automatic Merge --- .../common/hooks/use_external_link.ts | 15 ++++++-- .../external_link/external_link.test.tsx | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/webapp/channels/src/components/common/hooks/use_external_link.ts b/webapp/channels/src/components/common/hooks/use_external_link.ts index 5125ce3845..4e980a60cc 100644 --- a/webapp/channels/src/components/common/hooks/use_external_link.ts +++ b/webapp/channels/src/components/common/hooks/use_external_link.ts @@ -21,6 +21,9 @@ export function useExternalLink(href: string, location: string = '', overwriteQu const userId = useSelector(getCurrentUserId); const config = useSelector(getConfig); const license = useSelector(getLicense); + const isCloudPreview = useSelector((state: GlobalState) => { + return state.entities?.cloud?.subscription?.is_cloud_preview === true; + }); const telemetryId = useSelector((state: GlobalState) => getConfig(state)?.TelemetryId || ''); const isCloud = useSelector((state: GlobalState) => getLicense(state)?.Cloud === 'true'); @@ -38,11 +41,19 @@ export function useExternalLink(href: string, location: string = '', overwriteQu // Determine server version const serverVersion = config?.BuildNumber === 'dev' ? config.BuildNumber : (config?.Version || ''); + // Determine utm_medium based on cloud preview, cloud, or regular + let utmMedium = 'in-product'; + if (isCloudPreview) { + utmMedium = 'in-product-preview'; + } else if (isCloud) { + utmMedium = 'in-product-cloud'; + } + const existingURLSearchParams = parsedUrl.searchParams; const existingQueryParamsObj = Object.fromEntries(existingURLSearchParams.entries()); const queryParams = { utm_source: 'mattermost', - utm_medium: isCloud ? 'in-product-cloud' : 'in-product', + utm_medium: utmMedium, utm_content: location, uid: userId, sid: telemetryId, @@ -54,5 +65,5 @@ export function useExternalLink(href: string, location: string = '', overwriteQu parsedUrl.search = Object.entries(queryParams).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); return [parsedUrl.toString(), queryParams]; - }, [href, isCloud, location, overwriteQueryParams, telemetryId, userId, config, license]); + }, [href, isCloud, isCloudPreview, location, overwriteQueryParams, telemetryId, userId, config, license]); } diff --git a/webapp/channels/src/components/external_link/external_link.test.tsx b/webapp/channels/src/components/external_link/external_link.test.tsx index e8a7e44496..862688651a 100644 --- a/webapp/channels/src/components/external_link/external_link.test.tsx +++ b/webapp/channels/src/components/external_link/external_link.test.tsx @@ -73,6 +73,40 @@ describe('components/external_link', () => { ); }); + it('should use in-product-preview utm_medium for cloud preview workspaces', () => { + const state = { + ...initialState, + entities: { + ...initialState.entities, + general: { + ...initialState?.entities?.general, + config: { + DiagnosticsEnabled: 'true', + }, + }, + cloud: { + subscription: { + is_cloud_preview: true, + }, + }, + }, + }; + renderWithContext( + + {'Click Me'} + , + state, + ); + + expect(screen.queryByText('Click Me')).toHaveAttribute( + 'href', + expect.stringMatching('utm_medium=in-product-preview'), + ); + }); + it('should preserve query params that already exist in the href', () => { const state = { ...initialState,