fix: update tracking on homepage widgets (#24153)

This commit is contained in:
Adrien L 2025-08-13 11:32:10 +02:00 committed by GitHub
parent 9651e7ce33
commit 330c50cc41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 95 additions and 24 deletions

View File

@ -1,4 +1,4 @@
import { useAuth } from '@strapi/admin/strapi-admin';
import { useAuth, useTracking } from '@strapi/admin/strapi-admin';
import { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';
import { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';
import { useIntl } from 'react-intl';
@ -85,6 +85,7 @@ const LinkCell = styled(Link)`
`;
const KeyStatisticsWidget = () => {
const { trackUsage } = useTracking();
const { formatMessage, locale } = useIntl();
const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();
const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =
@ -216,6 +217,7 @@ const KeyStatisticsWidget = () => {
to={item.link}
key={`key-statistics-${key}`}
data-testid={`stat-${key}`}
onClick={() => trackUsage('didOpenKeyStatisticsWidgetLink', { itemKey: key })}
>
<Flex alignItems="center" gap={2}>
<Flex

View File

@ -7,7 +7,11 @@ import { Widget } from '../WidgetHelpers';
describe('Homepage Widget component', () => {
it('should render the widget with info from props', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }} icon={Cog}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
icon={Cog}
uid="plugin::test.test-widget"
>
actual widget content
</WidgetRoot>
);
@ -19,7 +23,10 @@ describe('Homepage Widget component', () => {
it('should render a spinner while a widget is loading', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
uid="plugin::test.test-widget"
>
<Widget.Loading />
</WidgetRoot>
);
@ -30,7 +37,10 @@ describe('Homepage Widget component', () => {
it('should render an error message when a widget fails to load', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
uid="plugin::test.test-widget"
>
<Widget.Error />
</WidgetRoot>
);
@ -41,7 +51,10 @@ describe('Homepage Widget component', () => {
it('should render a custom error message when provided', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
uid="plugin::test.test-widget"
>
<Widget.Error>Custom error message</Widget.Error>
</WidgetRoot>
);
@ -52,7 +65,10 @@ describe('Homepage Widget component', () => {
it('should render a no data message when a widget has no data', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
uid="plugin::test.test-widget"
>
<Widget.NoData />
</WidgetRoot>
);
@ -62,7 +78,10 @@ describe('Homepage Widget component', () => {
it('should render a custom no data message when provided', () => {
render(
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
<WidgetRoot
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
uid="plugin::test.test-widget"
>
<Widget.NoData>Custom no data message</Widget.NoData>
</WidgetRoot>
);

View File

@ -175,7 +175,6 @@ export interface EventWithoutProperties {
| 'willEditEditLayout'
| 'willEditEmailTemplates'
| 'willEditEntryFromButton'
| 'willEditEntryFromHome'
| 'willEditEntryFromList'
| 'willEditReleaseFromHome'
| 'willEditFieldOfContentType'
@ -187,7 +186,7 @@ export interface EventWithoutProperties {
| 'willEditStage'
| 'willFilterEntries'
| 'willInstallPlugin'
| 'willOpenAuditLogDetails'
| 'willOpenAuditLogDetailsFromHome'
| 'willUnpublishEntry'
| 'willSaveComponent'
| 'willSaveContentType'
@ -411,6 +410,27 @@ interface DidStartGuidedTour {
};
}
interface WillEditEntryFromHome {
name: 'willEditEntryFromHome';
properties: {
entryType: 'edited' | 'published' | 'assigned';
};
}
interface DidOpenHomeWidgetLink {
name: 'didOpenHomeWidgetLink';
properties: {
widgetUID: string;
};
}
interface DidOpenKeyStatisticsWidgetLink {
name: 'didOpenKeyStatisticsWidgetLink';
properties: {
itemKey: string;
};
}
type EventsWithProperties =
| CreateEntryEvents
| PublishEntryEvents
@ -436,7 +456,10 @@ type EventsWithProperties =
| DidUpdateCTBSchema
| DidSkipGuidedTour
| DidCompleteGuidedTour
| DidStartGuidedTour;
| DidStartGuidedTour
| DidOpenHomeWidgetLink
| DidOpenKeyStatisticsWidgetLink
| WillEditEntryFromHome;
export type TrackingEvent = EventWithoutProperties | EventsWithProperties;
export interface UseTrackingReturn {

View File

@ -12,6 +12,7 @@ import { Widget } from '../../components/WidgetHelpers';
import { useEnterprise } from '../../ee';
import { useAuth } from '../../features/Auth';
import { useStrapiApp } from '../../features/StrapiApp';
import { useTracking } from '../../features/Tracking';
import { FreeTrialEndedModal } from './components/FreeTrialEndedModal';
import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';
@ -23,15 +24,21 @@ import type { WidgetType } from '@strapi/admin/strapi-admin';
* WidgetRoot
* -----------------------------------------------------------------------------------------------*/
interface WidgetRootProps extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link'> {
interface WidgetRootProps
extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {
children: React.ReactNode;
}
export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link }: WidgetRootProps) => {
export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid }: WidgetRootProps) => {
const { trackUsage } = useTracking();
const { formatMessage } = useIntl();
const id = React.useId();
const Icon = icon;
const handleClickOnLink = () => {
trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });
};
return (
<Flex
width="100%"
@ -61,6 +68,7 @@ export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link }: Widget
style={{ textDecoration: 'none' }}
textAlign="right"
to={link.href}
onClick={handleClickOnLink}
>
{formatMessage(link.label)}
</Typography>
@ -157,7 +165,12 @@ const HomePageCE = () => {
<Grid.Root gap={5}>
{filteredWidgets.map((widget) => (
<Grid.Item col={6} s={12} key={widget.uid}>
<WidgetRoot title={widget.title} icon={widget.icon} link={widget.link}>
<WidgetRoot
title={widget.title}
icon={widget.icon}
link={widget.link}
uid={widget.uid}
>
<WidgetComponent component={widget.component} />
</WidgetRoot>
</Grid.Item>

View File

@ -30,7 +30,7 @@ const LastActivityTable = ({ items }: { items: AuditLog[] }) => {
};
const handleRowClick = (document: AuditLog) => () => {
trackUsage('willOpenAuditLogDetails');
trackUsage('willOpenAuditLogDetailsFromHome');
const link = getAuditLogDetailsLink(document);
navigate(link);
};
@ -74,7 +74,7 @@ const LastActivityTable = ({ items }: { items: AuditLog[] }) => {
<IconButton
tag={Link}
to={getAuditLogDetailsLink(item)}
onClick={() => trackUsage('willOpenAuditLogDetails')}
onClick={() => trackUsage('willOpenAuditLogDetailsFromHome')}
label={formatMessage({
id: 'global.details',
defaultMessage: 'Details',

View File

@ -32,7 +32,13 @@ const CellTypography = styled(Typography)`
white-space: nowrap;
`;
const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) => {
const RecentDocumentsTable = ({
documents,
type,
}: {
documents: RecentDocument[];
type: 'edited' | 'published';
}) => {
const { formatMessage } = useIntl();
const { trackUsage } = useTracking();
const navigate = useNavigate();
@ -46,7 +52,9 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
};
const handleRowClick = (document: RecentDocument) => () => {
trackUsage('willEditEntryFromHome');
trackUsage('willEditEntryFromHome', {
entryType: type,
});
const link = getEditViewLink(document);
navigate(link);
};
@ -95,7 +103,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
<IconButton
tag={Link}
to={getEditViewLink(document)}
onClick={() => trackUsage('willEditEntryFromHome')}
onClick={() => trackUsage('willEditEntryFromHome', { type })}
label={formatMessage({
id: 'content-manager.actions.edit.label',
defaultMessage: 'Edit',
@ -140,7 +148,7 @@ const LastEditedWidget = () => {
);
}
return <RecentDocumentsTable documents={data} />;
return <RecentDocumentsTable documents={data} type="edited" />;
};
/* -------------------------------------------------------------------------------------------------
@ -170,7 +178,7 @@ const LastPublishedWidget = () => {
);
}
return <RecentDocumentsTable documents={data} />;
return <RecentDocumentsTable documents={data} type="published" />;
};
/* -------------------------------------------------------------------------------------------------

View File

@ -19,7 +19,13 @@ const CellTypography = styled(Typography)`
white-space: nowrap;
`;
const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) => {
const RecentDocumentsTable = ({
documents,
type,
}: {
documents: RecentDocument[];
type: 'assigned';
}) => {
const { formatMessage } = useIntl();
const { trackUsage } = useTracking();
const navigate = useNavigate();
@ -33,7 +39,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
};
const handleRowClick = (document: RecentDocument) => () => {
trackUsage('willEditEntryFromHome');
trackUsage('willEditEntryFromHome', { entryType: type });
const link = getEditViewLink(document);
navigate(link);
};
@ -85,7 +91,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
<IconButton
tag={Link}
to={getEditViewLink(document)}
onClick={() => trackUsage('willEditEntryFromHome')}
onClick={() => trackUsage('willEditEntryFromHome', { entryType: type })}
label={formatMessage({
id: 'content-manager.actions.edit.label',
defaultMessage: 'Edit',
@ -130,7 +136,7 @@ const AssignedWidget = () => {
);
}
return <RecentDocumentsTable documents={data} />;
return <RecentDocumentsTable documents={data} type="assigned" />;
};
export { AssignedWidget };