analytics-reporter schedules GA4 report publishing on a Postgres queue
Lightweight analytics reporting and publishing tool for Digital Analytics Program's Google Analytics 360 data.
At a glance
- What is it?
- The 18F analytics-reporter pulls Google Analytics 4 data through the Google Analytics Data API and publishes flattened reports for the Digital Analytics Program, using a Postgres database as a job queue. Reports are hardcoded in JSON, and the integration tests hit the live Google API.
- Who is it for?
- analytics-reporter is worth adopting if you run a Google Analytics 4 property and need scheduled, reproducible exports rather than a browser dashboard, particularly if you already work with the Digital Analytics Program data model, since the report definitions follow that shape.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 24 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A command line tool for a government wide analytics property
analytics-reporter is a lightweight system for publishing analytics data from the Digital Analytics Program Google Analytics 4 government wide property. It uses the Google Analytics Data API v1 to acquire the data, then processes it into a flat data structure that is easy to store, diff and chart. The project is used together with a separate analytics-reporter-api repository, and the pair powers the government analytics website at analytics.usa.gov, which is a useful reference for what the output is meant to look like. The package manifest describes it as a lightweight command line tool for reporting and publishing analytics data from a Google Analytics account, and the entry point is a bin entry called analytics. It is a backend utility rather than a user interface, and the people who benefit from it directly are the data teams and site owners who need a scheduled extract, not the analysts who want a chart in a browser.
The database doubles as the job queue, with a publisher and a consumer
The architecture is a queue based pipeline, and the README says so directly. The application has multiple jobs that run at scheduled intervals, and the deploy directory holds the publisher script that describes the jobs and the timing at which they are kicked off. The database functions as a queue using the pg-boss library. The publisher process puts messages on the queue that represent analytics reports and how those reports should be fetched, processed and published, and one or more consumer processes receive those messages in parallel and execute the corresponding tasks. Two consequences follow from that design. Reports are fetched in parallel rather than one after another, so a large property with many agency reports finishes faster. And the queue is durable, since the state lives in Postgres rather than in process memory, which means a consumer restart does not lose the work list. The application can publish to AWS S3, to a local file, to stdout, or to the database, in JSON or CSV format.
The report catalogue is hardcoded JSON, which is the sharpest limitation
Available reports are named and described in two files under the reports directory, api.json and usa.json, and the README notes that for now they are hardcoded into the repository. This is the constraint that shapes everything else about the tool. Adding a metric means editing a JSON definition, pushing it and waiting for the deployment pipeline, not filling in a query in a user interface. For the Digital Analytics Program use case, where the set of published reports is a public contract, that is a reasonable design. For an organisation that wants to explore its own property, it is a wall. The flat data structure the tool produces is what makes the hardcoded list workable, since the shape of each output is predictable and can be diffed across runs, but it also means the schema of the reports is coupled to the code. Anyone extending it needs to read the development and deployment process document, which the README points to as the description of how features are added.
Local setup needs Node 22, a Postgres on 5432 and a migration
The prerequisites are NodeJS above version 22.x and a Postgres database running, or Docker installed. The dependency install and the migration step are the two commands you need first.
npm installnpm run migrateThe repository ships a docker-compose file that starts an empty database on port 5432, and the compose file defines a Postgres 16 service with the database named analytics-reporter, a user named analytics and a volume for the data directory.
docker-compose upThe application itself runs as two processes, a queue publisher and a queue consumer, so they have to be started separately, with the dotenv package supplying the environment variables.
# start publisher
npx dotenv -e .env.analytics node -- deploy/publisher.js# start consumer
npx dotenv -e .env.analytics node -- deploy/consumer.jsConfiguration comes from a .env file created from the env.example template, which is listed in the .gitignore and should not be committed. The Google Analytics side needs a service account: you enable the Google Analytics API in the developer dashboard, create a service account, generate a JSON private key, take the client email from it, and grant that address the read, analyze and collaborate permission on the analytics profiles you want to publish.
One report for one agency can be produced without the whole pipeline
For development and debugging there is a shortcut that skips the queue entirely. Setting AGENCY_NAME and ANALYTICS_REPORT_IDS in your .env file, with the values taken from the agencies file in the deploy directory, lets you run a single named report.
# general format
npx dotenv -- npm start -- --only=REPORT_NAME --json --output=/path/to/output# example
npx dotenv -- npm start -- --only=devices --json --output=./outputThe output flag points at a path on disk and the json flag selects the format, so you end up with a file you can inspect directly rather than a row in a database. This is the loop most contributors will actually use, and it is worth knowing that it bypasses the publisher and consumer entirely, which means it will not exercise the scheduling or the parallel consumption behaviour. The README also documents a set of git hooks in the hooks directory, installed with npm run install-git-hooks, which check out the current npm packages on branch change events and run the linter on pre-commit, and the linting itself is handled by ESLint and Prettier through npm run lint and npm run lint:fix.
The integration tests call the real Google Analytics API
The unit tests need a local Postgres, and the repository provides a compose file for it so you can start a test database with docker-compose up against the test compose file, or run your own server. Once a database is available, npm test runs the suite with a pre-test hook that applies the migrations first, and npm run coverage adds the NYC coverage reporting on top. The integration tests are a different matter. They require the Google Analytics credentials to be set in the environment, configured through the dotenv-cli package, and the README warns that these tests make real requests to Google Analytics APIs and should be run sparingly to avoid being rate limited in the live apps that use the same account credentials. That is an unusual and honest warning to ship. The tests are written with Cucumber, with the feature files and support code in the features directory and a cucumber.yml at the top level, which means the behaviour of a report is described in readable scenarios rather than only in assertions.
Cloud.gov deployment, a licence question and a moving default branch
The two application components are deployed to cloud.gov for development, staging and production, using GitHub Actions, and the CI workflow file holds the details of both the CI and the deployment process. The repository also carries the manifests for both components on cloud.gov, a Procfile, a New Relic configuration file, and a knexfile for cloud.gov that sits alongside the local knexfile, which suggests the same migrations are applied to both environments with different connection settings. Two caveats are worth flagging. The licence is reported as a custom one that GitHub cannot classify at the repository level, while the package manifest states CC0-1.0, so the LICENSE file is the document to read rather than the badge. And the default branch is develop while the build badge in the README points at the master branch, which is a small sign of a branch strategy in motion. The release history is short, v2.0.0 in March 2024 described as outputting both Universal Analytics and GA4 data, and a 1.0.0 from 2015, while the last push was on 2026-09-29.
Editorial conclusion
analytics-reporter is worth adopting if you run a Google Analytics 4 property and need scheduled, reproducible exports rather than a browser dashboard, particularly if you already work with the Digital Analytics Program data model, since the report definitions follow that shape. It is a poor fit if you need a self service report builder, because the available reports are hardcoded in the repository, or if you cannot accept a test suite that makes real requests against a live analytics account. Verify three things before you deploy it: that your service account has the read and analyze permission on the analytics profile you intend to publish, that the report list in the reports directory covers the questions you need, and that the two application components, publisher and consumer, run as separate processes in your target environment. The licence is listed as a custom one at the repository level while the package manifest states CC0-1.0, and the last push was on 2026-09-29.
Frequently asked questions
What does the 18F analytics-reporter do?
It is a lightweight system that uses the Google Analytics Data API v1 to pull data from the Digital Analytics Program Google Analytics 4 government wide property and processes it into a flat data structure. It is used with the analytics-reporter-api project to power the analytics.usa.gov website.
How do I add a new report to analytics-reporter?
Reports are named and described in the api.json and usa.json files under the reports directory, and for now they are hardcoded into the repository. The README points to the development and deployment process document for how features are added.
What does it take to run analytics-reporter locally?
NodeJS above version 22.x and a Postgres database or Docker. You install dependencies with npm install, start the database with docker-compose up, run npm run migrate for the schema, and then start the publisher and the consumer as separate processes.
Do the integration tests call the real Google Analytics API?
Yes. The integration tests require Google Analytics credentials in the environment, are run through the dotenv-cli package with the cucumber features, and the README warns that they make real requests and should be run sparingly to avoid rate limiting the live apps using the same credentials.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/18f-analytics-reporter)Was this useful?