Setup & FAQ

Get your city live in a few minutes

Sign in, connect PostHog or Google Analytics, and share the link. Here’s everything you need — including where to grab your credentials.

1 · Getting started

  1. 1
    Sign in

    Continue with Google on the home page — that creates your city.

  2. 2
    Brand it

    In the dashboard set your name, colour and logo. That names your city and its in-world sign.

  3. 3
    Add data

    Pick a data source: PostHog or Google Analytics to publish, or Manual to preview numbers you type in.

  4. 4
    Share

    Copy your publishable URL and send it, or embed it with the <iframe> snippet.

2 · Connect PostHog

You’ll need three things: a Project ID, a Personal API key (scoped to only query:read), and your host. We never see anything beyond your user counts.

  1. Open PostHog

    Log in to your PostHog project (US or EU cloud, or self-hosted).

    Open PostHog ↗
  2. Create a personal API key

    Settings → Personal API keys → “Create personal API key”. Under scopes choose “Performing analytics queries” (that is the query:read scope) and nothing else, then copy the phx_… key — it is shown only once.

    Personal API keys ↗
  3. Find your Project ID

    Settings → Project. The Project ID is the number near the top (it also appears in the URL as /project/12345).

    Project settings ↗
  4. Note your host

    US cloud → https://us.posthog.com · EU cloud → https://eu.posthog.com · self-hosted → your own URL.

  5. Paste into User Town

    Dashboard → Data source → PostHog → enter Project ID, API key and host → Save.

3 · Connect Google Analytics (GA4)

One click with Connect with Google — read-only, no service-account file, and you pick your property from a dropdown:

  1. Click “Connect with Google”

    Dashboard → Data source → Google Analytics → Connect with Google. You’ll be sent to Google to sign in — no file to download, nothing to paste.

  2. Approve read-only access

    Grant the read-only Analytics permission (analytics.readonly). We only ever read your total and active user counts — we can’t change anything in your Analytics.

  3. Pick your property

    Back on the dashboard, choose your GA4 property from the dropdown (we list the ones your Google account can read), then Save. The city starts reading live numbers.

Advanced: connect with a service-account JSON instead

Prefer not to use Google sign-in (e.g. a locked-down GA org, or a shared service account)? You can upload a read-only service-account key:

  1. Find your Property ID

    Google Analytics → Admin (⚙) → Property details. The Property ID is a number like 123456789 (a GA4 property, not a UA one).

    Open Google Analytics ↗
  2. Enable the Analytics Data API

    In Google Cloud, pick/create a project and enable the “Google Analytics Data API”.

    Enable Data API ↗
  3. Create a service account + JSON key

    Google Cloud → IAM & Admin → Service Accounts → Create. Then Keys → Add key → JSON, and download the file.

    Service accounts ↗
  4. Give it Viewer access

    GA4 Admin → Property Access Management → “+” → add the service-account email (the client_email inside the JSON) with the read-only Viewer role on just that property.

  5. Paste into User Town

    Dashboard → Data source → Google Analytics → open “Advanced: use a service-account JSON” → enter the Property ID and paste the whole JSON → Save.

4 · Platform status → weather

Your platform’s live state becomes the city’s weather. Choose where that status comes from — three ways, easiest first:

  1. Manual

    Dashboard → Platform status → Manual, then pick a status from the dropdown. Simplest option — and the only way to set the fun ones (Recovering / Winter) yourself.

  2. Status page

    Dashboard → Platform status → Status page, then paste your public status-page URL. We auto-detect Statuspage.io, Instatus, Hyperping and Better Stack (plus generic JSON) and map the current indicator to weather. No API key needed — it reads the same page your users see.

  3. Health check

    Dashboard → Platform status → Health check, then paste any URL we can ping. We derive status from the HTTP response: 200 & fast = operational, 200 but slow = degraded, 4xx = degraded, 503 = maintenance, other 5xx = outage, unreachable/timeout = outage.

  4. Custom JSON (optional)

    On a health-check URL you can instead return {"status":"operational"} — any of operational, maintenance, degraded, outage, recovering, winter — and we use it directly instead of inferring from the HTTP code. A clean way to drive the weather from your own logic.

Whichever source you pick, the status maps to weather like this:

☀️ OperationalClear skies — all good.
🔧 MaintenanceRain — scheduled downtime.
⛈️ DegradedStorm — partial issues.
🔥 OutageFire — you are down.
🌈 RecoveringRainbow — back online.
❄️ WinterSnow — a cold snap.

Status refreshes about every 25 seconds, and it’s read server-side — your status/health URL is never called from visitors’ browsers.

FAQ

Do I need PostHog AND Google Analytics?

No — pick one. Manual mode is also there if you just want to preview numbers you type in (it can’t be published). You can switch anytime.

Is my data safe?

If you connect PostHog or GA, the API key / service-account JSON (or OAuth token) is encrypted at rest, used server-side only, and never sent to the public city page — and we ask for least-privilege scopes (PostHog query:read only; GA read-only Viewer / analytics.readonly on one property). Visitors only ever see the resulting numbers and weather.

What do the numbers actually control?

Total users set the city’s size (homestead → metropolis). Active users fill the streets with traffic and crowds. Your platform status becomes the weather.

How does the weather work?

Set a status source in the dashboard: Manual (pick it yourself), Status page (paste your public status-page URL — we auto-detect Statuspage.io, Instatus, Hyperping, Better Stack, and generic JSON), or Health check (any URL we ping, mapping HTTP codes to weather). We map the result to weather automatically and refresh it every ~25s.

Which status pages are supported?

Statuspage.io / Atlassian, Instatus, Hyperping and Better Stack are auto-detected from their public JSON. Many other pages work via a generic JSON fallback. If yours is HTML-only or unusual, use the Health check option (or expose a small {"status":"..."} JSON) instead.

The weather is stuck / not updating — why?

Make sure the status source is set and saved, and that the URL is your public status page (not a private admin page). Status pages must expose a JSON endpoint; HTML-only pages can’t be read — switch to Health check for those. Note Recovering and Winter are manual-only moods and won’t come from a status page or health check.

Can I embed the city on my own site?

Yes. Grab the publishable URL and drop it in an iframe: <iframe src="https://theusertown.com/city/your-slug" width="100%" height="500"></iframe>.

How often does it update?

The published city and dashboard preview poll your source every couple of minutes, so numbers and weather stay current without hammering your analytics account.

Why are my numbers 0?

The source may have returned no data yet, or the credentials aren’t saved — double-check the API key scope (PostHog: query:read) or that the GA4 connection/service account has Viewer access to the property you selected.

Ready?

Open your dashboard →