Analytics
Arc CMS reports visits to Google Analytics from the browser, and, once you connect your GA4 property, shows the last 28 days of traffic on the admin dashboard.
What it is
Two separate parts, set up in different places:
| Part | What it does | Set up with |
|---|---|---|
| Tracking | Firebase Analytics (GA4) runs in the browser on the pages the app draws, recording page views and Arc CMS's own events. Published content pages and static pages carry no tracking code | The measurementId in your Firebase web config |
| Dashboard analytics | Cloud Functions read your GA4 property and the admin dashboard shows the numbers | A Google OAuth client, on Admin, Settings, Analytics |
Besides page views, tracking records these events:
| Events | When |
|---|---|
content_list_view, content_detail_view, public_page_view, share_click | A content list, a content item or a static page is viewed, or a share button is clicked |
waitlist_view, waitlist_signup_submit, waitlist_otp_verify, waitlist_signup_complete, waitlist_existing_user, waitlist_error | Steps of a signup form (see Signup forms) |
unsubscribe_view | The unsubscribe page is viewed |
Content events need the Content feature, and signup form events the Signup forms feature. UTM parameters in the address are saved as user properties. After a form sign-up, the visitor is linked to their user id and the form. Nothing from their email address is sent.
The dashboard shows nine numbers for the last 28 days, each compared with the 28 days before: Users, New Users, Sessions, Bounce Rate, Avg. Duration, Pages/Session, Pageviews, Event Count and Engaged Sessions. Beside them are five lists: Top Pages, Traffic Sources, Devices, Top Countries, and AI assistants (sessions sent by AI assistants, which GA4 files under Referral).
The other cards on the dashboard (content, users, sign-ups) are counted from Firestore, not from Google Analytics; see Use the admin area. App install numbers are on Installable app (PWA).
Turn it on or off
Analytics is the feature analytics, on unless you list it in off in src/custom/features.ts (see Choose your app's features). Off, no Google Analytics code loads in the browser at all, and the dashboard's analytics section, Admin, Settings, Analytics (its tile, its link on the dashboard, and the page at both /admin/settings/analytics and /admin/analytics-setting) and the five functions below go.
On, tracking runs whenever your Firebase web config has a measurementId. The dashboard part shows numbers only after you connect a property, and stops when you disconnect it.
Consent
Each install chooses whether Google Analytics waits for the visitor's consent, per Firebase project:
npm run arc:configure -- --analytics-consent=required
| Value | Who is tracked |
|---|---|
always | The default, as Arc CMS always did: every visitor, from the first page. The site usage banner, if on, only records the visitor's choice. |
required | Only visitors who clicked accept on the site usage banner. Until then no Google Analytics code is even downloaded, and no cookie is set. With the banner off, nobody is tracked, because nobody can accept. |
The value is written to arccms.config.json (key analyticsConsent) and src/environments/arc-install.ts; build and deploy the website for it to apply. Admin, Settings, Analytics and the dashboard say in one line which of these is happening, and warn when nobody is tracked because the banner is off, with a link to turn it on.
In required mode, after the visitor accepts, the same events are sent as in always mode: Google's page view, the screen views (named as AngularFire's screen tracking names them), the user id, and the events above. The numbers then cover only those who accepted.
The Firebase Analytics code is a chunk of its own, never part of the code every page loads. It is downloaded when tracking starts: as the site opens in always mode, after the visitor accepts in required mode, and never with the feature off.
- Withdrawing. A visitor who accepted and later rejects is not tracked from that moment, and Google's
_gacookies are deleted. - Asking again. The banner shows once. To let visitors change their mind, add a "Cookie settings" link that calls
reopen()onSiteUsageService(src/app/pages/admin/(settings)/site-usage/site-usage.service.ts); the banner then shows again. - Per device. The choice is kept in the visitor's browser only (local storage,
arc_site_usage), so they are asked again in another browser or after clearing site data. - Pages never tracked. A route with
data: { analytics: false }is never tracked, in either mode, and neither is any page below it (see Add pages and routes).
Set it up
Tracking
Copy the web app config from the Firebase console, including measurementId, into your environment file (see Configure a project; the shape is in src/environments/environment.example.ts). Nothing else is needed.
Dashboard analytics
In the Google Cloud console for your Firebase project, enable the Google Analytics Data API and the Google Analytics Admin API.
Create an OAuth client ID of type Web application. Add your site's address and
http://localhost:5173under both Authorized JavaScript origins and Authorized redirect URIs, and also addhttp://localhostunder Authorized JavaScript origins. If Google asks for a consent screen first, choose External and fill in the app name and emails.Open Admin, Settings, Analytics, click Configure Analytics, paste the client ID and secret, and click Save Credentials. The page has these steps as a guide, with the addresses to copy.
Click Connect Google Analytics and allow access in the Google popup, with the account that can see your Analytics property.
Arc CMS lists the Analytics properties the account can see, under Select GA4 Property: pick the one your site reports to and click Connect. The first numbers are fetched straight away.
Use it
Open the admin dashboard. When the numbers are more than 5 minutes old, opening it fetches fresh ones; Refresh fetches them at any time. The header shows when they were last fetched, and View Full Analytics opens your project's Analytics page in the Firebase console.
To connect another property or another account, click Disconnect on Admin, Settings, Analytics, then connect again. Disconnecting revokes Arc CMS's access at Google.
Extend it
Log your own events with AnalyticsService (src/app/core/analytics/analytics.service.ts): log(name, params), setUserProperties() and setUserId(). They send nothing unless this visitor may be tracked on this page right now (the feature, the consent mode and the route), so your events follow the same rules as Arc CMS's. Do not import @angular/fire/analytics or firebase/analytics yourself: that would bypass consent, and a test fails if any file outside src/app/core/analytics does. GaTrackingService (src/shared/services/ga-tracking.service.ts) is core; call its methods, but put new event helpers in your own code in src/custom/.
The dashboard's metrics and lists are fixed in core (functions/src/AnalyticsDashboard/analyticsHelpers.ts). A different set is a feature request for Arc CMS, not a change in an app.
What it stores
| Where | Holds |
|---|---|
Settings/analytics | The OAuth client ID and secret, the access and refresh tokens, the chosen property, and whether it is connected |
Settings/analytics_status | No secrets: whether it is connected, the property name and id, the measurement id, and when data was last fetched |
AnalyticsDashboards/analyticsData | The last fetched numbers and lists, the date range and the property id |
Nothing is kept in Storage. The Cloud Functions, all callables:
| Function | Does |
|---|---|
connectGoogleAnalytics | Exchanges the Google authorization for tokens, finds the property, fetches the first numbers |
selectAnalyticsProperty | Saves the property you picked |
refreshAnalyticsData | Fetches fresh numbers |
disconnectGoogleAnalytics | Revokes access, clears the connection and deletes the stored numbers |
testAnalyticsConnection | A debugging check for a service-account setup; the admin pages do not use it |
See Cloud Functions and Data model.
Who can do what
| Who | Can |
|---|---|
| Admin | Read and write Settings/analytics and AnalyticsDashboards; connect, pick a property, refresh and disconnect |
| Signed-in person | Read Settings/analytics_status (no secrets) |
The client secret is shown masked on the settings page and is only sent to Google by the functions.
Troubleshooting
| You see | Why, and what to do |
|---|---|
| "No refresh token received" | Google remembers an earlier grant. Remove the app's access at https://myaccount.google.com/permissions and connect again. |
| "OAuth client ID and secret not configured" | Save the credentials before you connect. |
| "Google Analytics access has been revoked. Please reconnect." | The grant expired or was removed at Google. Connect again. |
| The Google popup shows an origin or redirect error, or "Authorization timed out" | The address you are on is not in the OAuth client's origins and redirect URIs; add it in the Google Cloud console. For a timeout, allow popups for your site. |
| Dashboard shows placeholders, no numbers | The stored numbers are for another property. Click Refresh. |
| "No GA4 property selected." | No property was picked when you connected, or the account can see none. On Admin, Settings, Analytics, click Disconnect, connect again, and pick a property. |
| No page views in Google Analytics | Check measurementId in the environment file, and look for Analytics in the browser's network requests. With analyticsConsent required, nothing is sent until you accept the site usage banner. |
| "Not tracking anyone" on Settings or the dashboard | The install waits for consent and the site usage banner is off. Turn the banner on (Admin, Settings, Site Usage), or set --analytics-consent=always if consent is not needed. |
| Far fewer visitors than before | With required, only visitors who accept are counted. That is expected. |