How to set up Dirigible Analytics using a Google Cloud Service Account
GA4 Service Account Setup Guide
This guide covers three tasks needed to give an application read-only programmatic access to a Google Analytics 4 (GA4) property:
- Creating a service account in Google Cloud
- Generating the service account's JSON key
- Retrieving the GA4 property number
The work spans two separate consoles: the Google Cloud Console (where the service account and key live) and Google Analytics (where you grant the account access and find the property number).
Before you begin
You will need:
- A Google account that can administer a Google Cloud project (create one if you don't have it).
- Admin-level access on the GA4 property you want to read β or someone who has it and can complete the access-granting step.
- About 10 minutes.
One prerequisite that isn't covered in the three numbered sections but is required for any of this to work: the Google Analytics Data API must be enabled on your Cloud project. To enable it, go to the Cloud Console, open APIs & Services β Library, search for "Google Analytics Data API", and click Enable. (If you also plan to programmatically list which properties the account can see, enable "Google Analytics Admin API" as well.)
1. Creating a service account
A service account is a non-human identity β an email address your application authenticates as. It lives inside a Google Cloud project.
Steps
- Go to the Google Cloud Console: https://console.cloud.google.com
- Using the project dropdown in the top bar, select an existing project or click New Project, give it a name (for example,
ga4-dashboards), and click Create. A single project can serve multiple GA4 properties, so you don't need one project per client. - Open the navigation menu (β°) β APIs & Services β Credentials.
- Click + Create Credentials at the top, then choose Service account.
- Under Service account details, enter a descriptive name such as
ga4-reader. Google automatically generates an email address for the account in the form:ga4-reader@your-project-id.iam.gserviceaccount.comNote this email β you will need it later when granting access in Google Analytics.
- Click Create and Continue.
- You will reach an optional step titled "Grant this service account access to the project." Leave the role field blank and continue. A Google Cloud (IAM) role does not grant any Google Analytics access β that comes solely from the access grant you make inside Analytics. Leaving it blank keeps the account at least privilege: it can do nothing in your Cloud project, which is exactly what you want for an identity that only reads analytics data.
- If the wizard won't let you proceed with an empty field, you can still click Continue / Done without selecting anything; the role really is optional. Do not grant a project-level "Viewer" or any other role out of caution β it wouldn't help and would only add unnecessary access.
- Skip the final optional step (granting users access to the service account) and click Done.
Result
You now have a service account with no permissions anywhere yet. It can't touch your Cloud project, and it can't read any analytics data until you explicitly grant it access in Google Analytics (covered alongside Section 3).
2. Creating the service account JSON key
The JSON key is the credential your application uses to authenticate as the service account. It is a long-lived secret β treat it like a password.
Steps
- In the Cloud Console, go to APIs & Services β Credentials (or IAM & Admin β Service Accounts).
- Find the service account you created and click its name to open it.
- Open the Keys tab.
- Click Add Key β Create new key.
- Choose JSON as the key type and click Create.
-
A
.jsonfile downloads automatically to your computer. This file is the credential.Critical security notes
-
You cannot re-download this file. If you lose it, delete the key and create a new one. There is no recovery.
- Store it outside your web root. It must never be in a publicly fetchable location. For a server application, place it somewhere like
/home/youruser/private/ga-key.jsonand reference it by an absolute path in your configuration. - Never commit it to version control. Add its path to
.gitignore. Leaked keys in public repositories are a common breach vector. - Do not paste it into a database field or settings page that could be read back through your application's UI if avoidable. Referencing a file path stored in a server-side config constant is safer than storing the key body in a database.
- Rotate and delete unused keys. Service account keys do not expire on their own. Establish a cadence (for example, rotate annually) and delete any key that is no longer in use.
What the key can and cannot do
Because the service account has no Cloud IAM roles and (after Section 3) only Viewer access to one property, a leaked key's worst case is read-only access to that single property's data β it cannot modify Analytics, cannot reach your Cloud resources, cannot create additional keys for itself, and cannot escalate its own access. Keeping the scope this tight is what makes the key's blast radius small, so the main discipline this setup requires is good key hygiene.
3. Retrieving the property number from GA4
The property number (also called the Property ID) is the numeric identifier that goes into every Data API request as properties/123456789. This is the same step where you grant the service account access, since both happen in the Google Analytics admin area.
Grant the service account access (required first)
The property number is only useful once the service account can read the property. To grant access:
- Go to Google Analytics: https://analytics.google.com
- Click Admin (the gear icon, bottom-left).
- Choose the scope of access:
- Property Access Management β grants access to a single property. Recommended for least privilege.
- Account Access Management β grants access to every property under the account. Broader; use only if you intentionally want the account to see all current and future properties.
- Click the + button, then Add users.
- Paste the service account email (from Section 1, step 5).
- Set the role to Viewer (read-only). Do not grant a higher role for a reporting integration.
- Optionally, apply data restrictions β No Cost Metrics and/or No Revenue Metrics β to withhold spend or revenue figures even from this read-only account.
- Untick "Notify new users by email" β there is no inbox behind a service account.
-
Click Add.
Find the property number
-
Still in Admin, make sure the correct property is selected in the property column.
- Click Property details (in some versions this is Property Settings).
- The Property ID is the numeric value displayed near the top, for example:
123456789 - Use it in API calls as:
properties/123456789
Important: do not confuse it with the Measurement ID
| Identifier | Looks like | Used for |
|---|---|---|
| Property ID (what you need) | 123456789 (numeric) |
Data API requests (properties/123456789) |
| Measurement ID | G-XXXXXXXXXX |
The on-page tracking tag; not used for API access |
If your API calls fail with an error about the property not being found, the most common cause is using the G- Measurement ID instead of the numeric Property ID.
Putting it together
After completing all three sections you will have:
- A service account email:
ga4-reader@your-project-id.iam.gserviceaccount.com - A JSON key file stored securely outside your web root
- A numeric Property ID, for example
123456789 - The service account granted Viewer access on that property
To confirm the chain works end to end, make arunReportcall to the Data API using the JSON key and the property ID. If rows come back, everything is wired correctly. If you get a permission error, re-check that the service account email was added as a Viewer on the exact property whose ID you are querying.
Quick verification checklist
- [ ] Google Analytics Data API enabled on the Cloud project
- [ ] Service account created with no Cloud IAM role
- [ ] JSON key downloaded and stored outside the web root (and in
.gitignore) - [ ] Service account email added as Viewer on the target property
- [ ] Numeric Property ID recorded (not the
G-Measurement ID) - [ ] Test
runReportcall returns data