Add script fetch api stats from plausible

pull/2293/head
Jérémy Rialland 2022-09-08 19:28:33 +02:00 committed by Jérémy Rialland
parent 0f69388e1a
commit 6a4606155a
4 changed files with 119 additions and 37 deletions

View File

@ -0,0 +1,52 @@
import 'dotenv/config.js'
import 'isomorphic-fetch'
const fetchApiStats = async (page, start, end, interval) => {
const url =
'https://plausible.io/api/v1/stats/timeseries?' +
Object.entries({
site_id: 'mon-entreprise.urssaf.fr/api',
period: 'custom',
date: start + ',' + end,
interval,
metrics: 'pageviews,visitors',
filters: 'event:page==' + page,
})
.map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
.join('&')
const result = await fetch(url, {
headers: new Headers({
Authorization: `Bearer ${process.env.PLAUSIBLE_API_KEY}`,
}),
})
return result.json()
}
export const apiStats = async (start, end, interval) => {
const names = ['evaluate', 'rules', 'rule']
const data = Object.values(
(
await Promise.all([
fetchApiStats('/api/v1/evaluate', start, end, interval),
fetchApiStats('/api/v1/rules', start, end, interval),
fetchApiStats('/api/v1/rules/*', start, end, interval),
])
)
.flatMap(({ results }, i) =>
results.map(({ date, pageviews }) => ({ date, [names[i]]: pageviews }))
)
.reduce(
(acc, el) => (
acc[el.date]
? (acc[el.date] = { ...acc[el.date], ...el })
: (acc[el.date] = el),
acc
),
{}
)
)
return data
}

View File

@ -3,6 +3,7 @@ import 'isomorphic-fetch'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { apiStats } from './fetch-api-stats.js'
import { createDataDir, writeInDataDir } from './utils.js'
const matomoSiteVisitsHistory = JSON.parse(
@ -180,7 +181,9 @@ async function fetchDailyVisits() {
(await fetchApi(buildSiteQuery(last60days, 'D')))[0].Rows
)
return { pages, site }
const { start, end } = last60days
return { pages, site, api: await apiStats(start, end, 'date') }
}
async function fetchMonthlyVisits() {
@ -198,7 +201,9 @@ async function fetchMonthlyVisits() {
),
]
return { pages, site }
const { start, end } = last36Months
return { pages, site, api: await apiStats(start, end, 'month') }
}
async function fetchUserAnswersStats() {
@ -292,20 +297,29 @@ async function main() {
)
return
}
const visitesJours = await fetchDailyVisits()
const visitesMois = await fetchMonthlyVisits()
const satisfaction = uniformiseData(
flattenPage(await fetchApi(buildSatisfactionQuery()))
).map((page) => {
// eslint-disable-next-line no-unused-vars
const { date, ...satisfactionPage } = {
month: new Date(new Date(page.date).setDate(1)),
...page,
const [
visitesJours,
visitesMois,
rawSatisfaction,
retoursUtilisateurs,
nbAnswersLast30days,
] = await Promise.all([
fetchDailyVisits(),
fetchMonthlyVisits(),
fetchApi(buildSatisfactionQuery()),
fetchUserFeedbackIssues(),
fetchUserAnswersStats(),
])
const satisfaction = uniformiseData(flattenPage(await rawSatisfaction)).map(
(page) => {
// eslint-disable-next-line no-unused-vars
const { date, ...satisfactionPage } = {
month: new Date(new Date(page.date).setDate(1)),
...page,
}
return satisfactionPage
}
return satisfactionPage
})
const retoursUtilisateurs = await fetchUserFeedbackIssues()
const nbAnswersLast30days = await fetchUserAnswersStats()
)
writeInDataDir('stats.json', {
visitesJours,
visitesMois,
@ -314,7 +328,7 @@ async function main() {
nbAnswersLast30days,
})
} catch (e) {
console.log(e)
console.error(e)
}
}
main()

View File

@ -26,7 +26,7 @@ import { Page, PageChapter2, PageSatisfaction, StatsStruct } from './types'
import { formatDay, formatMonth } from './utils'
type Period = 'mois' | 'jours'
type Chapter2 = PageChapter2 | 'PAM'
type Chapter2 = PageChapter2 | 'PAM' | 'api-rest'
type Pageish = Page | PageSatisfaction
@ -105,11 +105,6 @@ const computeTotals = (
: data.map((d) => d.nombre).reduce((a, b) => a + b, 0)
}
interface BrushStartEndIndex {
startIndex?: number
endIndex?: number
}
interface StatsDetailProps {
stats: StatsStruct
}
@ -140,6 +135,9 @@ const StatsDetail = ({ stats }: StatsDetailProps) => {
if (!chapter2) {
return rawData.site
}
if (chapter2 === 'api-rest') {
return rawData.api.map(({ date, ...nombre }) => ({ date, nombre }))
}
return filterByChapter2(rawData.pages as Pageish[], chapter2)
}, [period, chapter2])
@ -233,17 +231,21 @@ const StatsDetail = ({ stats }: StatsDetailProps) => {
endIndex={endDateIndex}
/>
<H3>
Cumuls pour la période{' '}
{period === 'jours'
? `du ${formatDay(slicedVisits[0].date)} au ${formatDay(
slicedVisits[slicedVisits.length - 1].date
)}`
: `de ${formatMonth(slicedVisits[0].date)}` +
(slicedVisits.length > 1
? ` à ${formatMonth(slicedVisits[slicedVisits.length - 1].date)}`
: '')}
</H3>
{slicedVisits.length > 0 && (
<H3>
Cumuls pour la période{' '}
{period === 'jours'
? `du ${formatDay(slicedVisits[0].date)} au ${formatDay(
slicedVisits[slicedVisits.length - 1].date
)}`
: `de ${formatMonth(slicedVisits[0].date)}` +
(slicedVisits.length > 1
? ` à ${formatMonth(
slicedVisits[slicedVisits.length - 1].date
)}`
: '')}
</H3>
)}
<Grid container spacing={2}>
<BigIndicator
@ -387,8 +389,10 @@ function SimulateursChoice(props: {
<Select
onSelectionChange={(val) => {
props.onChange(
typeof val === 'string' && val.length
typeof val === 'string' && val.length && !isNaN(parseInt(val))
? getChapter2(simulateurs[parseInt(val)])
: val === 'api-rest'
? val
: ''
)
}}
@ -398,7 +402,11 @@ function SimulateursChoice(props: {
{[
<Item key={''} textValue="Tout le site">
<Emoji emoji="🌍" />
Tout le site
&nbsp;Tout le site
</Item>,
<Item key={'api-rest'} textValue="API REST">
<Emoji emoji="👩‍💻" />
&nbsp;API REST
</Item>,
...simulateurs.map((s, i) => (
<Item key={i} textValue={s.shortName}>

View File

@ -39,16 +39,24 @@ export enum SatisfactionLevel {
TrèsBien = 'très bien',
}
export interface Visites {
interface Visites {
pages: Page[]
site: Site[]
api: API[]
}
export interface Site {
interface Site {
date: string
nombre: number
}
interface API {
date: string
evaluate: number
rules: number
rule: number
}
export enum PageChapter2 {
AideDeclarationIndependant = 'aide_declaration_independant',
ArtisteAuteur = 'artiste_auteur',