Skip to content

Repository files navigation

Local GA4 Dashboard on macOS

This project runs a local Flask dashboard that reads GA4 data through the Google Analytics Data API using numeric Property IDs (not G-XXXXXXX measurement IDs).

1) Prerequisites

  • macOS with python3 available
  • A GA4 property for each site you want to report on
  • A Google Cloud service account key JSON file with access to the GA4 properties

2) Find the IDs you need

For each GA4 website:

  1. Open Google Analytics.
  2. Go to Admin.
  3. In the Property column, open Property Settings.
  4. Copy the numeric Property ID.

3) Configure local files

  1. Copy the example site map:
    • cp config/sites.example.json config/sites.json
  2. Edit config/sites.json and replace placeholder IDs with your own numeric IDs.
  3. Put your service account key file at:
    • credentials.json

If your key file is elsewhere, set:

export GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/your-key.json"

3b) Safe for GitHub

This project can be published to a public GitHub repo as long as you do not commit your local secrets.

Ignored automatically:

  • credentials.json
  • config/sites.json
  • .venv/
  • __pycache__/

Safe files to commit:

  • config/sites.example.json
  • README.md
  • server.py
  • templates/
  • launcher scripts

If someone clones the repo, they can create their own local setup without seeing your keys or site list.

4) Install and run

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 server.py

Open:

4b) Double-click launchers (Finder)

  • start_dashboard.command: creates config/sites.json if missing, installs deps, opens the dashboard, starts server in that Terminal window.
  • setup_sites.command: interactive wizard that asks how many sites to track and which IDs to use.
  • edit_sites.command: opens config/sites.json in TextEdit.
  • stop_dashboard.command: stops the server process listening on port 5000.

Start/stop behavior:

  • Double-click start_dashboard.command to run the server.
  • If port 5000 is busy, the launcher automatically picks the next open localhost port.
  • Leave that Terminal open while using the dashboard.
  • Stop with Ctrl+C in that Terminal, or double-click stop_dashboard.command.

4c) Add the sites you want to track

Fastest option:

  • Double-click setup_sites.command
  • Enter how many sites you want to track
  • Enter each site's display name and GA4 Property ID
  • Optionally enter domain, account_id, realtime_url, and logo_url

Manual option:

Edit config/sites.json with this exact structure:

{
  "www.example.com": "123456789",
  "Store Dashboard": {
    "property_id": "987654321",
    "domain": "store.example.com",
    "account_id": "270069835"
  },
  "Portfolio": {
    "property_id": "456789123",
    "logo_url": "https://example.com/path/to/logo.png",
    "realtime_url": "https://analytics.google.com/analytics/web/#/a270069835p456789123/realtime/overview?params=_u..nav%3Dmaui"
  }
}
  • Left side: any display name you want.
  • Right side can be either:
    • just a GA4 numeric Property ID string, or
    • an object with property_id plus optional domain, logo_url, account_id, and realtime_url.
  • Add as many sites as needed, separated by commas.

Logo behavior:

  • If logo_url is set, that logo is used.
  • Else if domain is set, the dashboard fetches a favicon from that domain.
  • Else if the site name looks like a domain (for example example.com), it uses that automatically.
  • Otherwise it shows an initials badge.

Realtime link behavior:

  • If realtime_url is set, that exact GA4 realtime URL is used.
  • Else if account_id is set, the dashboard builds a realtime URL like #/aACCOUNTpPROPERTY/realtime/overview.
  • Otherwise it falls back to a property-based realtime GA4 URL.

For publishing:

  • Keep your real config/sites.json local only.
  • Commit only config/sites.example.json with fake placeholder values.
  • Keep your service account JSON out of the repo.

5) Expected output

  • Total Combined Traffic chart (sum across all configured properties)
  • Site snapshot cards at the top with quick KPIs (Live 30m, Today (std), Org 7d, Org 30d)
  • Realtime Geo map at the top of the dashboard with an All Sites or per-site selector
  • SEO sanity line per site (search sanity, organic share, robots status, sitemap presence)
  • Summary counters (Organic 7d, Organic 30d, Searched Sites (7d), Robots Issues)
  • One chart per configured site (last 30 days active users)
  • Last updated timestamp plus Refresh now button (auto-refresh every 5 minutes)
  • Link pills per site for Open in GA4, Realtime GA4, and robots.txt

6) Common errors

  • No sites configured: create config/sites.json.
  • Live 30m does not match Today (std):
    • Live 30m is realtime users from the last 30 minutes.
    • Today (std) is GA4 standard reporting and can lag before it catches up.
  • Robots sanity flags (blocked/missing/error):
    • open the robots.txt pill on the card.
    • if blocked or missing, apply the recommendation shown in the card's SEO line.
  • Permission denied or API auth errors:
    • confirm credentials.json path
    • ensure the service account has at least Viewer access in each GA4 property

6b) robots.txt quick fixer

If a card shows Robots: blocked or Robots: missing, a safe starter robots file is:

User-agent: *
Allow: /
Sitemap: https://yourdomain.com/sitemap.xml

Use your real domain in the sitemap URL.

About

Local GA4 dashboard for macOS with realtime geo, SEO checks, and GA4 links

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages