Case Study

Building a content analytics
dashboard for editorial decisions

Organisation
BellaNaija
Role
Solo build
Year
2026
Type
Internal analytics tooling

The problem

Before

The editorial team published Features content regularly but had no easy way to see how individual pieces were performing in terms of traffic. GA4 existed but required manual querying every time anyone wanted an answer. Nobody was consistently monitoring whether content was being read, shared, or had gone completely stale.

What was needed

A single view that automatically matched published content from WordPress against its GA4 traffic data, surfaced pieces that had received zero views, flagged evergreen content worth re-promoting, and was fast enough to check in under five minutes.

The deeper issue was that editorial decisions were being made on instinct rather than data. Good content was being left to go stale while the team kept producing new pieces without knowing what was actually landing. The tool needed to change that default behaviour, not just answer occasional one-off questions.

What I built

An internal Google Apps Script web application deployed at go.bellanaija.co/featuretracker. The app pulls live content data from the WordPress REST API, matches each published post against its GA4 performance metrics via the GA4 Data API, and presents everything in a searchable, filterable dashboard.

Key features: summary cards giving an at-a-glance view of overall content performance, trend charts showing traffic over time, zero-view alerts flagging content that has received no traffic at all, evergreen alerts identifying older high-performing content worth pushing again, a search and pagination layer for navigating the full content archive, and CSV export for when someone needs to analyse the data offline.

One technical constraint worth noting: GA4's Data API has a row limit per call. Pulling all traffic data and filtering afterwards would either miss content or hit rate limits. The solution was a custom inListFilter approach — querying specific post URLs directly rather than pulling everything — which keeps response times fast and stays within API limits even with a large content archive.

Google Apps Script GA4 Data API WordPress REST API JavaScript HTML / CSS

Outcome

60%
Reduction in manual reporting time for the team
Live
Data refreshed from WordPress and GA4 on each load
2
Automated alert types that catch issues without anyone asking

The team went from manually querying GA4 and cross-referencing with the CMS to having a single view that answered the most common editorial questions in one load. The zero-view alert was the feature that got used most consistently — it surfaced content that had been published and forgotten, prompting re-promotion decisions that would not have happened otherwise.

What I learned

01Dashboards fail when nobody has a reason to open them. The automated alerts built a habit loop — the tool created its own reason to be checked. Passive monitoring is more sustainable than expecting people to remember to open a dashboard proactively.
02GA4's API has real constraints that only become visible at production scale. Testing with a small dataset gave a false sense of how the tool would behave against a full content archive. The inListFilter approach was a solution that came from hitting that wall in a real deployment, not a sandbox.
03The most valuable feature was not the one I expected. I built the trend charts thinking they would be the main draw. The zero-view alert — which I added almost as an afterthought — turned out to be what people actually used and talked about. The lesson: the feature that shows people something they did not already know will always beat the feature that presents data they could have found themselves.