Configuration
Configuration
Section titled “Configuration”Two sections of appsettings.json are involved: one for the provider’s connection — Flowcourier:Matomo (three values required: Endpoint, TokenAuth and SiteId) or Flowcourier:GoogleAnalytics (one: PropertyId, plus the service account under Flowcourier:Analytics:Google) — and Flowcourier:Analytics for everything shared by the Analytics section (all optional).
Matomo connection
Section titled “Matomo connection”{ "Flowcourier": { "Matomo": { "Enabled": true,
// Connection (required) "Endpoint": "https://analytics.example.com/", "TokenAuth": "<token_auth>", "SiteId": 1,
// Where the pages are tracked (recommended) "SiteUrl": "https://www.example.com",
// Multi-site installs (optional) "Sites": [ { "RootContentKey": "6f1a…", "SiteId": 2, "SiteUrl": "https://other.example" } ],
// Behaviour "ReportCacheSeconds": 300, "RealtimeCacheSeconds": 15, "RealtimeMinutes": 30, "TimeoutSeconds": 30 } }}Environment variables work too: Flowcourier__Matomo__TokenAuth, Flowcourier__Matomo__SiteId, and so on.
| Setting | Default | Description |
|---|---|---|
Enabled |
true |
Master switch. When false the backoffice shows a “disabled” note and Matomo is never called. |
Endpoint |
— | Base URL of your Matomo, with or without a trailing slash or index.php. |
TokenAuth |
— | A Matomo API token (Administration → Personal → Security → Auth tokens). Tokens created with Only allow secure requests work: the token is only ever sent as a POST field, never in a URL. |
SiteId |
— | The Matomo website ID (Administration → Websites → Manage). |
SiteUrl |
Matomo’s main URL for the site | Public base URL the pages are tracked under; used to build the per-page URLs for the document tab. |
Sites |
[] |
Per-root-node overrides for multi-site installs — see below. |
ReportCacheSeconds |
300 |
How long a date-ranged report is cached on the server before Matomo is asked again. |
RealtimeCacheSeconds |
15 |
Cache for the Realtime payload. The dashboard polls every 30 seconds; several open tabs share one Matomo call. |
RealtimeMinutes |
30 |
The Realtime “active now” window. |
TimeoutSeconds |
30 |
Per-request timeout for Matomo calls. |
The effective values are shown (token masked) under Settings → Flowcourier → Matomo.
Google Analytics connection
Section titled “Google Analytics connection”{ "Flowcourier": { "GoogleAnalytics": { "Enabled": true,
// The GA4 property (required) — the numeric id, not the G-… measurement id "PropertyId": "123456789",
// Where the pages are tracked (recommended) "SiteUrl": "https://www.example.com",
// Multi-site installs (optional) "Sites": [ { "RootContentKey": "6f1a…", "PropertyId": "987654321", "SiteUrl": "https://other.example" } ],
// Behaviour "ReportCacheSeconds": 300, "RealtimeCacheSeconds": 15, "RealtimeMinutes": 30, "TimeoutSeconds": 30 }, "Analytics": { // The service account (required) — shared with Search Console "Google": { "ServiceAccountJsonPath": "/secrets/ga-service-account.json" } } }}Environment variables work too: Flowcourier__GoogleAnalytics__PropertyId, Flowcourier__Analytics__Google__ServiceAccountJson, and so on.
| Setting | Default | Description |
|---|---|---|
Enabled |
true |
Master switch. When false the backoffice shows a “disabled” note and Google is never called. |
PropertyId |
— | The GA4 property id (Admin → Property details), a number; properties/123456789 is accepted. A G-… measurement id is refused and the status says why. |
SiteUrl |
the property’s web data stream URI | Public base URL the pages are tracked under. Page filters go to Google as host + path; when empty the package reads the first web data stream’s default URI (Admin API). |
Sites |
[] |
Per-root-node properties for multi-site installs — see below. |
ReportCacheSeconds |
300 |
How long a date-ranged report is cached on the server before Google is asked again. GA4 data is hours behind anyway. |
RealtimeCacheSeconds |
15 |
Cache for the Realtime payload. The dashboard polls every 30 seconds; several open tabs share one Google call. |
RealtimeMinutes |
30 |
The Realtime “active now” window; a standard GA4 property reports at most 30 minutes. |
TimeoutSeconds |
30 |
Per-request timeout for Google calls. |
The key itself lives under Flowcourier:Analytics:Google (ServiceAccountJson inline, or ServiceAccountJsonPath); see Search Console for that section. The effective values are shown — with the service account’s e-mail, never the key — under Settings → Flowcourier → Google Analytics.
Running Matomo and Google Analytics together
Section titled “Running Matomo and Google Analytics together”Some sites run both tools — typically Matomo for privacy-friendly, consent-free statistics and Google Analytics 4 for marketing. Install both provider packages and configure each one as above. The Analytics section reads one of them at a time; Flowcourier:Analytics:Provider says which:
{ "Flowcourier": { "Analytics": { "Provider": "google-analytics" // or "matomo" } }}Or as an environment variable: Flowcourier__Analytics__Provider=matomo.
The active provider feeds everything: the dashboards, the document Analytics tab, the findings strip, the live badge, the Copilot tools and AI Visibility. The other one is installed but not read. Figures from the two tools are never mixed — Matomo and GA4 count visits differently, so a combined number would match neither.
Switching is a configuration change and takes effect without a restart; reopen the dashboard to see the other provider’s figures. Each provider caches its own reports, so nothing from one shows up under the other.
When Provider is empty, the choice is automatic:
- Only one provider package installed → that one (the setting is not needed).
- Both installed, only one enabled and configured → that one. To switch off one provider without uninstalling it, set its
Enabledtofalse. - Both set up → Matomo, and the Analytics Overview shows a note asking you to set
Provider.
A Provider value that names a package that is not installed is ignored (the rules above apply) and the Overview says so.
Visitor journeys (the Visits dashboard and per-visit panel) come from Matomo only, so they appear only while Matomo is the active provider. Google Analytics cannot report individual visits.
The Overview dashboard shows which provider the figures come from whenever both are installed.
Shared Analytics settings
Section titled “Shared Analytics settings”{ "Flowcourier": { "Analytics": { "SiteUrl": "https://www.example.com", "Provider": "", "GrantAdminSectionAccess": true, "RealtimeBadge": { "Enabled": true, "PollSeconds": 60 }, "PageSpeed": { "Enabled": false, "ApiKey": "" }, "SearchConsole": { "Enabled": false, "Property": "" }, "Google": { "ServiceAccountJson": "", "ServiceAccountJsonPath": "" } } }}| Setting | Default | Description |
|---|---|---|
SiteUrl |
the provider’s tracked URL | Public base URL used to build page URLs for PageSpeed Insights and Search Console. |
Provider |
automatic | matomo or google-analytics: which provider the section reads when both are installed. See Running Matomo and Google Analytics together. |
GrantAdminSectionAccess |
true |
On startup, add the Analytics section to the Administrators group if it is missing. |
RealtimeBadge:Enabled |
true |
The live visitor count on the Analytics section in the top bar. Every open backoffice tab polls for it (the server caches the answer for 15 s). |
RealtimeBadge:PollSeconds |
60 |
Badge refresh interval (minimum 15). |
PageSpeed:* |
off | See PageSpeed Insights. |
SearchConsole:*, Google:* |
off | See Search Console. |
VisitorJourney:Enabled |
true |
The Visits dashboard and the per-visit journey. Set to false to remove the dashboard, answer the endpoints with 409 and stop any request for individual-visitor data reaching the provider. Only does anything when the installed provider answers per visit (Matomo does, Google Analytics cannot). |
VisitorJourney:PageSize |
50 |
Visits per page in the list. The visits log is not archived data, so a wide page costs the Matomo host more. |
VisitorJourney:MaxVisitorVisits |
25 |
Most earlier visits shown for one visitor. |
AI:* |
on | The “Explain and suggest” button, when Flowcourier.Umbraco.Analytics.AI is installed. See Ask the Copilot. |
The effective values are shown (secrets masked) under Settings → Flowcourier → Analytics.
Who can see individual visitors
Section titled “Who can see individual visitors”The Visits dashboard, the journey panel and the Realtime report all show individual visits, so they require Analytics section access, checked on the server rather than only in the browser — every signed-in backoffice user can reach the API, because editors need the document Analytics tab. A user without the section gets a 403 and is offered no journey surface at all.
The token
Section titled “The token”The token carries the rights of the Matomo user it was created for. Create it for a user that only has view access to the website so the token can never change anything in Matomo. Rotate it from Matomo whenever you like — the package picks up a changed appsettings.json value without a restart.
Keep it out of source control: an environment variable, a user-secrets file or your host’s secret store all bind to the same setting.
SiteUrl and multi-site installs
Section titled “SiteUrl and multi-site installs”On Google Analytics the same idea applies with the property in place of the site: SiteUrl (or the web data stream’s default URI) supplies the host the page filter is narrowed to, and Sites[] maps content roots to property ids ("PropertyId" instead of "SiteId"). Without a host the page is filtered on its path alone, which over-counts on a property that tracks several hosts.
On Matomo, Matomo stores absolute page URLs. To show a page’s numbers, the document tab combines a base URL with the page’s route (/about-us/) and asks Matomo for exactly that URL. The base URL is:
SiteUrl, when set — use this whenever the Umbraco host differs from the tracked host (staging, an internal hostname, a load balancer), or when Matomo’s registered main URL is not the canonical one.- Otherwise the main URL registered for the website in Matomo.
For an Umbraco install hosting several websites, map each content root to its Matomo site:
"Sites": [ { "RootContentKey": "6f1a1b2c-…", "SiteId": 2, "SiteUrl": "https://second.example" }, { "RootContentKey": "9e8d7c6b-…", "SiteId": 3 }]RootContentKey is the key (GUID) of the root node — copy it from the node’s Info tab. A page reports against the closest configured ancestor; anything not covered falls back to the top-level SiteId/SiteUrl. The Analytics section dashboards always show the top-level site.
Findings
Section titled “Findings”The findings strip on the document tab compares the last Flowcourier:Findings:WindowDays full days (default 28) with the same length before. The traffic thresholds live under Flowcourier:Analytics:Findings:
| Setting | Default | Description |
|---|---|---|
MinPageviews |
50 |
Below this many pageviews in the window no traffic rule fires. |
NewPageDays |
14 |
Pages younger than this are not reported for having no traffic. |
TrafficDropPercent |
30 |
Visits down by at least this much vs the previous window. |
LandingEntranceShare |
0.4 |
Share of visits starting on the page above which it counts as a landing page. |
BounceAboveMedianFactor |
1.5 |
Landing-page bounce at or above the site median × factor. |
ExitAboveMedianFactor |
1.5 |
Mid-funnel exit rate at or above the site median × factor. |
SearchAfterPercent |
10 |
Site searches right after the page, as a share of its pageviews. |
ServerTimeFactor / ServerTimeMinMs |
2 / 300 |
Page server time vs the site’s, with a floor in milliseconds. |
MinPagesForBaseline |
5 |
The site medians need at least this many pages with enough traffic. |
CacheMinutes |
10 |
How long a page’s computed findings are kept. |
The site baseline (median bounce and exit rates over pages with at least MinPageviews, site server time) comes from the provider — Matomo reads its pages report and the PagePerformance plugin; Google Analytics supplies the bounce median only (GA4 has no exit metric and no server timing), so the exit and server-time rules never fire there.
Which documents get the tab
Section titled “Which documents get the tab”The document Analytics tab hides on nodes that are not web pages — settings, data folders, product data on a headless site. Detection is automatic (a template, traffic on the URL, whether the public site serves the URL), and configuration under Flowcourier:Pages overrides it:
{ "Flowcourier": { "Pages": { "IncludeDocumentTypes": [], "ExcludeDocumentTypes": ["siteSettings", "dataFolder"], "ExcludeRoutePrefixes": ["/data/"], "UseDeliveryApiDisallowedTypes": true, "SiteUrl": "", "Probe": { "Enabled": true, "TimeoutSeconds": 5 } } }}| Setting | Default | Description |
|---|---|---|
IncludeDocumentTypes |
— | When set, only these document types are pages. The simplest answer on a headless site. |
ExcludeDocumentTypes |
— | Document types that are never pages. |
ExcludeRoutePrefixes |
— | Routes under these prefixes are never pages. |
UseDeliveryApiDisallowedTypes |
true |
Types listed in Umbraco’s DeliveryApi:DisallowedContentTypeAliases count as data. |
SiteUrl |
the analytics provider’s tracked URL | Where the public site is probed. Set it on a headless site whose front end is not the Umbraco host; without it, and with the Delivery API enabled, nothing is probed and undecided nodes keep the tab. |
Probe:Enabled |
true |
Ask the front end (HEAD, then GET) when nothing else decides. |
The effective settings and the reasoning are shown under Settings → Flowcourier → Page detection.
AI Visibility
Section titled “AI Visibility”Flowcourier:Analytics:AI:Visibility — the prompt set sampled through your
own AI profiles with web search, off by default and licensed (Analytics Pro,
key at Flowcourier:Licenses:AnalyticsPro). Every setting, the daily budget and
what a share means are on the AI Visibility
page. Flowcourier:Analytics:AI (the Copilot tools’ “Explain and suggest”) is
unaffected.
Section access
Section titled “Section access”The Analytics section is an ordinary backoffice section. Administrators get it on the first start after install (Flowcourier:Analytics:GrantAdminSectionAccess); grant it to other groups under Users → Groups → (group) → Sections → Analytics. The document tab needs no extra permission — anyone who can open the document sees it.
Caching
Section titled “Caching”Matomo archives reports rather than counting live, and GA4 processes them hours behind, so a five-minute server-side cache costs nothing in freshness while keeping the provider load (and, on Google, the API quota) flat when many editors have dashboards open. Set ReportCacheSeconds to 0 to disable it. The Realtime dashboard is cached for RealtimeCacheSeconds only.