Indie hackers, vibe coders and studios shipping more than one web or mobile app

Founders with several apps

AI tools made shipping cheap, so you run five apps — and five admin pages just to see who signed up. Vitrus puts every app in one panel: traffic, signed-in users, who came back, who you lost and who pays. One extra line per app, and your users' emails and names never reach our servers.

Get started free Read the docs

Questions it answers

Which of my apps is actually growing?

The Portfolio page puts every app side by side: visitors against the previous period, active, new and lost users, net, signups, paying users and revenue per currency, with a total row.

Who uses this app, and who never came back?

The Users page lists each signed-in user — under a made-up name, because no name is stored — with status (returning, one-time, signed up only), actions, active days, visits, joined and last active. Open a row for actions by day and recent visits.

Am I winning or losing users this month?

Lifecycle compares the period with the one before it: new, came back, lost, net and quick ratio, plus one-and-done and who became or stopped paying. The bridge always adds up, and every number opens its query.

Can I just ask my AI how my apps are doing?

Yes. Connect ChatGPT, Claude, Cursor or Claude Code over MCP and ask "which of my apps lost the most users this week?" — get_portfolio and get_lifecycle answer with the queries attached, so the assistant cites instead of guessing.

Does it work in my iOS or Flutter app?

Yes: Swift and Flutter/Dart SDKs send screens, actions and the hashed user id, with an offline queue. The app appears next to the website in the same workspace — as its own site, or the same one if you want web and app users counted as one.

Do I have to hand over my users' data?

No. The tracker hashes the user id in the browser before it is sent, the server hashes it again with a secret, and email, phone and name fields are dropped twice. No auth provider to connect, no admin keys to share.

Setting it up

In every app, where the user is signed in

vitrus.identify(user.id);   // hashed in the browser, never sent raw

Optional: sharper numbers

vitrus("signup");
vitrus("plan", { plan: "pro" });
vitrus("invoice_sent");   // your own actions

Ask your AI about all of them

claude mcp add vitrus --transport http https://app.vitrus.dev/mcp

Or add https://app.vitrus.dev/mcp as a custom connector in ChatGPT or Claude.

Related documentation

Other use cases