Skip to content

Commit

Permalink
API stats 💪 (#1018)
Browse files Browse the repository at this point in the history
* feat: add mtm campaign for tracking

* feat: add API stats

* chore: types
  • Loading branch information
XavierJp authored Apr 25, 2024
1 parent 6051cfa commit 5e55195
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 41 deletions.
28 changes: 23 additions & 5 deletions clients/matomo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type IMatomoStats = {
agentUnknown: number;
visitorReturning: number;
visitorUnknown: number;
apiRequests: number;
}[];
monthlyNps: {
label: string;
Expand All @@ -30,6 +31,9 @@ export type IMatomoStats = {
redirectedSiren: { value: number; label: string }[];
};

const SITE_ID = '145';
const API_SITE_ID = '294';

const getLabel = (labelAsString: string, index: number) => {
if (
labelAsString.indexOf('SIRE') === 0 ||
Expand Down Expand Up @@ -63,6 +67,8 @@ type IMatomoMonthlyStat = {
nb_uniq_visitors_returning: number;
nb_visits_new: number;
nb_visits_returning: number;
nb_actions_returning: number;
nb_actions_new: number;
};

type IMatomoEventStat = { label: string; nb_events: number };
Expand All @@ -73,6 +79,7 @@ type IMatomoEventStat = { label: string; nb_events: number };
const computeStats = (
matomoMonthlyStats: IMatomoMonthlyStat[],
matomoAgentMonthlyStats: IMatomoMonthlyStat[],
matomoAPIMonthlyStats: IMatomoMonthlyStat[],
matomoCopyPasteEventStats: IMatomoEventStat[],
matomoEventsCategory: IMatomoEventStat[][]
) => {
Expand All @@ -91,13 +98,19 @@ const computeStats = (
nb_uniq_visitors_new: agentUnknown,
} = matomoAgentMonthlyStats[index];

const { nb_actions_returning: api_returning, nb_actions_new: api_new } =
matomoAPIMonthlyStats[index];

const apiRequests = (api_returning + api_new) * 100;

visits.push({
number,
label,
agentReturning,
agentUnknown,
visitorReturning,
visitorUnknown,
apiRequests,
});

redirectedSiren.push({
Expand Down Expand Up @@ -148,16 +161,20 @@ export const clientMatomoStats = async (): Promise<IMatomoStats> => {
const [
matomoMonthlyStats,
matomoAgentMonthlyStats,
matomoAPIMonthlyStats,
matomoCopyPasteEventStats,
matomoEventsCategory,
npsRecords,
] = await Promise.all([
httpGet<IMatomoMonthlyStat[]>(createPageViewUrl(), {
httpGet<IMatomoMonthlyStat[]>(createPageViewUrl(SITE_ID), {
timeout: constants.timeout.XXL,
}),
httpGet<IMatomoMonthlyStat[]>(createAgentPageViewUrl(), {
timeout: constants.timeout.XXL,
}),
httpGet<IMatomoMonthlyStat[]>(createPageViewUrl(API_SITE_ID), {
timeout: constants.timeout.XXL,
}),
httpGet<IMatomoEventStat[]>(createCopyPasteEventUrl(), {
timeout: constants.timeout.XXL,
}),
Expand All @@ -170,6 +187,7 @@ export const clientMatomoStats = async (): Promise<IMatomoStats> => {
...computeStats(
matomoMonthlyStats,
matomoAgentMonthlyStats,
matomoAPIMonthlyStats,
matomoCopyPasteEventStats,
matomoEventsCategory
),
Expand All @@ -190,11 +208,11 @@ export const clientMatomoStats = async (): Promise<IMatomoStats> => {
/**
* Compute matomo API url to extract page view count
*/
const createPageViewUrl = () => {
const createPageViewUrl = (siteId: string) => {
let baseUrl = routes.tooling.matomo.report.bulkRequest;
lastTwelveMonths().forEach((month, index) => {
baseUrl += `&urls[${index}]=`;
const subRequest = `idSite=145&period=month&method=VisitFrequency.get&module=VisitFrequency&date=${month.firstDay}`;
const subRequest = `idSite=${siteId}&period=month&method=VisitFrequency.get&module=VisitFrequency&date=${month.firstDay}`;

baseUrl += encodeURIComponent(subRequest);
});
Expand All @@ -205,15 +223,15 @@ const createPageViewUrl = () => {
const createAgentPageViewUrl = () => {
const agentConnecté = encodeURIComponent('Agent connecté');
const segment = encodeURIComponent('dimension1==' + agentConnecté);
const baseUrl = createPageViewUrl() + '&segment=' + segment;
const baseUrl = createPageViewUrl(SITE_ID) + '&segment=' + segment;
return baseUrl;
};

const createEventsCategoryUrl = () => {
let baseUrl = routes.tooling.matomo.report.bulkRequest;
lastTwelveMonths().forEach((month, index) => {
baseUrl += `&urls[${index}]=`;
const subRequest = `idSite=145&period=month&method=Events.getCategory&module=API&date=${month.firstDay}`;
const subRequest = `idSite=${SITE_ID}&period=month&method=Events.getCategory&module=API&date=${month.firstDay}`;
baseUrl += encodeURIComponent(subRequest);
});
return baseUrl;
Expand Down
92 changes: 56 additions & 36 deletions components/stats/trafic.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,59 @@
import { ChangeEvent, useState } from 'react';
import { IMatomoStats } from '#clients/matomo';
import { Select } from '#components-ui/select';
import { StackedBarChart } from '#components/chart/stack-bar';
import constants from '#models/constants';

export const TraficStats: React.FC<{
visits: {
number: number;
label: string;
agentUnknown: number;
agentReturning: number;
visitorReturning: number;
visitorUnknown: number;
}[];
}> = ({ visits }) => {
const [statsType, setStatsType] = useState<'agents' | 'users'>('users');
type IStatType = 'agents' | 'users' | 'api';

export const TraficStats: React.FC<Partial<IMatomoStats>> = ({
visits = [],
}) => {
const [statsType, setStatsType] = useState<IStatType>('users');

const data = {
datasets: [
{
label:
statsType === 'agents'
? 'Nombre d’agents récurrents'
: 'Nombre d’utilisateurs récurrents',
data: visits.map(({ label, visitorReturning, agentReturning }) => ({
y: statsType === 'agents' ? agentReturning : visitorReturning,
x: label,
})),
backgroundColor: constants.chartColors[0],
},
{
label:
statsType === 'agents'
? 'Nombre de nouveaux agents'
: 'Nombre de nouveaux utilisateurs',
data: visits.map(({ label, visitorUnknown, agentUnknown }) => ({
y: statsType === 'agents' ? agentUnknown : visitorUnknown,
x: label,
})),
backgroundColor: constants.chartColors[1],
},
],
datasets:
statsType === 'api'
? [
{
label: 'Nombre d’appels reçus par l’API Recherche d’Entreprises',
data: visits.map(({ label, apiRequests }) => ({
y: apiRequests,
x: label,
})),
backgroundColor: constants.chartColors[1],
},
]
: [
{
label:
statsType === 'agents'
? 'Nombre d’agents récurrents'
: 'Nombre d’utilisateurs récurrents',
data: visits.map(
({ label, visitorReturning, agentReturning }) => ({
y: statsType === 'agents' ? agentReturning : visitorReturning,
x: label,
})
),
backgroundColor: constants.chartColors[0],
},
{
label:
statsType === 'agents'
? 'Nombre de nouveaux agents'
: 'Nombre de nouveaux utilisateurs',
data: visits.map(({ label, visitorUnknown, agentUnknown }) => ({
y: statsType === 'agents' ? agentUnknown : visitorUnknown,
x: label,
})),
backgroundColor: constants.chartColors[1],
},
],
};

const onOptionChange = (e: ChangeEvent<HTMLInputElement>) => {
setStatsType(e.target.value as 'agents' | 'users');
setStatsType(e.target.value as IStatType);
};

return (
Expand Down Expand Up @@ -86,6 +96,7 @@ export const TraficStats: React.FC<{
options={[
{ value: 'users', label: 'utilisateurs' },
{ value: 'agents', label: 'agents' },
{ value: 'api', label: 'appels API' },
]}
defaultValue={'users'}
onChange={onOptionChange}
Expand All @@ -106,6 +117,15 @@ export const TraficStats: React.FC<{
2 visites dans le mois) est un marqueur de l’efficacité du service
</li>
</ul>
<p>
Nous suivons également le nombre d’appels reçus par{' '}
<a href="/donnees/api-entreprises">
notre API de Recherche d’entreprises
</a>
. Ce chiffre inclut les appels provenant du site{' '}
<b>Annuaire des Entreprises</b> et les appels externes, provenant
d’acteurs privés ou publics.
</p>
</>
);
};

0 comments on commit 5e55195

Please sign in to comment.