~/Alessandro Belli

Building MeTag Analyze: A Web Platform for Media Diary Research

Project Type: Research Software / Open Source
Role: Sole Developer (web platform & mobile app)
Technologies: PHP, Laravel, Vue.js, MySQL, Tailwind CSS
Repository: github.com/zemki/metag-analyze
Live Platform: mesoftware.org
Mobile App: Google Play · App Store

The Problem

Media and communication researchers have long relied on diary studies. A media diary asks participants to record each episode of media use close to when it happens: what they used, when it began and ended, and whatever extra dimensions the study cares about. The value is granular, time-stamped data from everyday life instead of distorted retrospective estimates. For decades the method ran on paper: tedious for participants, error-prone, and every page transcribed by hand before analysis could begin.

My Role

I have been the sole developer of MeTag since 2019, at ZeMKI, the Centre for Media, Communication and Information Research at the University of Bremen. MeTag is two pieces of software: the MeTag app participants install on their phones, and MeTag Analyze, the web platform researchers use to run their studies. I build both.

One Platform, Two Very Different Users

Every feature has to serve two people with opposite needs. The researcher wants expressive power. The participant needs near-zero friction, because logging an entry has to take seconds, every day, for weeks, or the data dries up. Flexibility lives on the researcher side; simplicity on the participant side.

For researchers, the platform covers the whole lifecycle of a study:

  • Design: a project holds the diary instrument: the fields participants fill in per entry, the study duration, and the central "what was used" field with its options.
  • Recruit: every participant becomes a case with its own study window and access, handed out as credentials or a QR code.
  • Collect: entries appear in the dashboard as participants submit them, and researchers can push reminders, immediate or scheduled, to phones that go quiet.
  • Mix modes: backend-only cases let the team type in data from paper diaries or interviews, so everything lands in one dataset.
  • Analyze: timeline charts per case, grouped views across cases, a project-wide treemap of usage, and Excel exports whose columns are generated from the study's own inputs.
  • Collaborate and reuse: co-researchers are invited by email; projects can be locked during collection and duplicated for the next wave.

For participants, all of that collapses into a short form on a phone: pick the entity, set begin and end, answer the researcher's questions. Done.

Technical Implementation

MeTag Analyze is a deliberate monolith: one Laravel application (Laravel 11 on PHP 8.3, MySQL 8) serving three consumers. Researchers get server-rendered Blade pages that mount Vue 3 components where interactivity is needed. The mobile app talks to a token-authenticated JSON API. Administrators get a Filament panel for feature toggles and platform settings. There is no single-page application anywhere: the "Vue islands in Blade" shape dates from 2019 and was modernized in place, never rewritten. For software one person has to keep alive for years, boring architecture is a feature.

An API that cannot break running studies

A diary study runs for weeks or months, and participants' phones talk to the API every day of that window. When a study is in week three of six, nothing about what the phone expects is allowed to change. That constraint produced the most consequential decision in the codebase: the mobile API is versioned, and every project is pinned to the contract it started with. Projects created before a cutoff date speak v1 forever; newer projects speak v2. The cutoff itself is an admin setting, changeable without a deploy. The concrete difference between the versions was the generalization from a hardcoded "media" concept to a configurable "entity" concept: v1 apps keep receiving the media field they expect, v2 receives entity.

The instrument is configuration, not code

Researchers aren't developers. When they create a project they compose the diary form from typed inputs: free text, a 1 to 5 scale, single choice, multiple choice, or an audio recording. The whole instrument is stored as a JSON definition on the project; entries store their answers as JSON keyed by input name. The mobile app renders its entry form from that definition at runtime, so every study gets a custom instrument without anyone writing code, and the platform never needs a database migration to support a new study design. On the web side, a registry maps each input type to a small renderer component, with a safe fallback for unknown types; adding a question type means one vocabulary entry and one renderer.

Logging in with a QR code

Typing credentials on a phone is exactly the kind of friction that kills participation, and we found out that during several workshops with students.
For newer projects, a researcher can hand a participant a QR code instead: it carries an encrypted payload tied to the participant's case; scanning it logs the phone in without typing anything. Codes can be revoked, un-revoked, and regenerated from the case dashboard, so a leaked code is a one-click fix, not a study incident.

Audio answers, treated with suspicion

Participants can answer questions by recording audio. Uploads are validated by their actual content rather than the client-declared type: the decoded data is inspected against a whitelist of audio and image formats, a defense against disguised executables. Accepted files are stored encrypted at rest, in per-project directories outside the web root, and streamed to researchers through authenticated routes with a custom audio player. Around this sit rate-limited authentication endpoints, a configurable IP blocklist, and ALTCHA for bot protection, a privacy-friendly proof-of-work alternative to CAPTCHAs: no Google, no tracking, on a platform handling sensitive research data.

Seven years, modernized in place

The first commit is from March 2019: Laravel 5.8, PHP 7.1, Vue 2, Sass. Today it runs Laravel 11 and PHP 8.3, Vue 3 with the Composition API, and Tailwind CSS 4 on plain CSS custom properties, built with Vite and tested with Pest, Jest, and Cypress in GitHub Actions, much of it from a focused 2025 modernization push. Six major Laravel versions and two major PHP versions were crossed while live data collection was running. The discipline never changed: incremental upgrades, the test suite as the safety net, the mobile API contract left untouched. The architecture is still the one from 2019, every layer inside it was swapped out in place, no rewrite, no downtime.

What I Learned

Research software cannot break running studies. An ordinary web app can ship a breaking change and apologize later. A diary study in week three of six cannot absorb any change to what the phone expects. Versioning the API and pinning every project to its contract is the decision that made everything else survivable.

Longevity beats novelty. The unglamorous choices are what made seven years of solo maintenance viable: server-rendered pages, one database, framework conventions over custom infrastructure. Modernizing in place, instead of rewriting, meant never losing the domain knowledge accumulated in the code.

Honest debt is part of the story. The user-facing concept is "entity", but the database tables underneath still say media, because renaming live tables under running studies was never worth the risk. The participant class is called Cases, because case is a reserved word. Small scars like these are what seven years in production look like, and I would rather point at them than hide them.

Impact

MeTag Analyze is open source under the MIT license and citable in academic publications through a Zenodo DOI (10.5281/zenodo.14237974); the MeTag app is shipped on both Google Play and the App Store. What it enables is simple: researchers design a diary study without writing code, participants carry it in their pocket, and the data arrives structured, time-stamped, and ready for analysis instead of stacked on paper.

Developed at ZeMKI, Centre for Media, Communication and Information Research, University of Bremen.