The daily metrics report was being filled manually by pulling from Kibana, MongoDB, and GA4 separately — every morning. I automated it.
Data Sources Unified
Kibana · MongoDB · GA4
Metrics Tracked
6 sections across user cohorts
Daily Auto-Populate
Google Apps Script trigger
Report Coverage
Users, Backentry, Eway, E-Invoice, Greetings, GST
Every morning, someone on the team was manually pulling numbers from three separate systems — Kibana for compliance event logs, MongoDB for user tier counts, Google Analytics 4 for feature-level engagement — and entering them column by column into an Excel sheet. The report had 88 rows across 6 sections and 25 date columns. It existed. It had to be filled every day. It took real time, introduced copy-paste errors, and the data was always from yesterday — by the time anyone read it, another 24 hours had passed.
KIBANA (Elasticsearch)
Backentry counts, E-Way Bill events, E-Invoice events. Event-level compliance logs from the backend.
MONGODB
Total users by tier (Classic, Growth, PRO, PRO+). User counts, plan activation status, cohort breakdown.
GOOGLE ANALYTICS 4
Send Greetings actions, GST Search usage. Feature-level engagement from the mobile app.
88 rows. 6 sections. 25 date columns (one per day, rolling). Sections: (1) Total Users by plan tier · (2) Backentry events · (3) E-Way Bill generation counts · (4) E-Invoice generation counts · (5) Send Greetings actions · (6) GST Search queries
One Apps Script function. Runs at 11 AM. Fills the next empty column.
KIBANA
Elasticsearch REST API. Query the event index with a date-range filter for yesterday. Aggregate by event_type. Return counts per compliance feature.
MONGODB
Atlas Data API (HTTP-based, no driver needed) OR direct pymongo connection. Query users collection by plan field. Count documents per tier.
GA4
Native Google Apps Script integration OR GA4 Data API. Date-range report for yesterday. Filter by event_name for greetings and GST search events.
I built the complete Apps Script scaffold — all 88 rows mapped to their source and their cell location, the column-finder logic, and placeholder functions for each data source. The team could fill in API credentials and connection strings as access was granted, section by section.
Implementation sequencing
Week 1: Move from Excel to Google Sheets. Set up GA4 Sheets add-on. Get Greetings and GST Search data flowing automatically — these require no backend access.
Week 2: Work with backend team for MongoDB Atlas API keys or reporting endpoint. Get user tier counts automated.
Week 3: Tackle Kibana — either direct Elasticsearch access or a CSV export workflow from the ops team. Each section becomes automated independently — gaps filled manually until full pipeline is live.
Why Apps Script not Python
Python with a scheduler (cron, GCP VM) would have been more powerful. Apps Script was the right call: it runs inside Google Workspace with no infrastructure to maintain, it integrates natively with GA4 and Sheets, and it's maintainable by non-engineers on the team. The constraint was the team, not the technology.
Manual time saved
Estimated 30-45 minutes per day across the team — just data entry
Error rate
Copy-paste errors from switching between 3 browser tabs eliminated
Latency
Data available at 11 AM daily rather than whenever someone finished pulling it manually
Scalability
Adding a new metric = adding one row + one API query, not a new manual process
Internal tooling is underrated as a PM signal. Fixing a data pipeline doesn't ship to users — but it gives the team faster, more accurate information every single day. Compounded across a quarter, that's dozens of better-informed product decisions. I prioritised this because I could see how the manual process was degrading data confidence on the team.
RETROSPECTIVE
I'd have started with the GA4 automation only and shipped it in 3 days. Starting with 'automate all 3 sources' created a coordination dependency on engineering for Kibana and MongoDB access. GA4 integration had zero blockers and could have delivered immediate value.
The scaffold I built assumes stable schemas. I should have added schema validation — if MongoDB adds a new user tier or Kibana renames an event field, the script would silently write zeros without any alert. Error handling and monitoring should have been in V1.
Presenting to leadership with a working 1-section automation (just GA4) would have been more compelling than a complete scaffold with placeholder functions. Show don't tell — even for internal tooling.