DEV Community

innerlove
innerlove

Posted on

My analytics said 15 users. The database said 2.

I have been building an AI companion app solo for seven months. Anonymous first, no login wall. Next.js, Supabase, Claude.

Every morning I read PostHog: about 40 visitors, 15 first conversations, 0 returns. So I worked the funnel. I cut a mandatory animation from 24 seconds to 8. I fixed a returning visitor bug that had been live for 68 days. I shipped passwordless sign in. Still zero.

The most boring thing I have ever built

A founder flag. One column, one view. It marks my own accounts and strips them out of every count.

alter table profiles add column if not exists is_founder boolean not null default false;

-- mark only addresses you have confirmed are yours
update profiles set is_founder = true where email in ('you@example.com');

create or replace view product_signal as
with real_people as (
  select id from profiles where is_founder = false
),
ranked as (
  select c.user_id, c.created_at,
         row_number() over (partition by c.user_id order by c.created_at) as rn
  from conversations c
  where c.user_id in (select id from real_people)
),
firsts  as (select user_id, created_at as first_at  from ranked where rn = 1),
seconds as (select user_id, created_at as second_at from ranked where rn = 2)
select
  (select count(*) from real_people)                        as people,
  (select count(*) from ranked)                             as conversations,
  (select count(*) from seconds)                            as had_a_second_conversation,
  (select count(*) from seconds s join firsts f using (user_id)
     where s.second_at - f.first_at <= interval '48 hours') as returned_within_48h,
  (select count(*) from memory mm
     where mm.user_id in (select id from real_people))      as memory_rows,
  (select max(created_at) from ranked)                      as newest_conversation;

-- Supabase serves views in public over its API. Keep this one private.
revoke all on public.product_signal from anon, authenticated;
Enter fullscreen mode Exit fullscreen mode

Then I stopped reading the dashboard and read select * from product_signal; instead.

What it said

Two external people. Ever.

One of them had six conversations and 390 messages in a single day, and came back within 48 hours. The other had one conversation and left. The 32 conversations and 5 accounts I had been reading all month were mostly me, testing my own product and calling it traction.

Two things I would tell myself in March

Your own testing is the loudest signal in an empty product. Analytics count browsers and sessions. In a product with almost no users, the founder is most of the data. Mark yourself where the data lives, and read that number first.

An empty room and a cold room are different problems. One stranger stayed for hours and came back the same day. The product was not failing people. Almost nobody had walked in. I had spent seven months on the funnel when the problem was that I never showed the thing to anyone. I rewrote the landing page instead. I researched a rename. With a finished page sitting there unpublished, I caught myself pricing domains again.

What I am building next

The thing that catches that. It starts from why you stopped instead of from your task list, gives you the smallest step another person can actually see, and logs what you shipped. No streaks, no due dates, nothing turns red. Letting something go counts as an ending, not a failure.

It does not exist yet, and the page says so: innerlove.app/build

Top comments (1)

Collapse
 
devsupport profile image
Dev Support •

Dear User,
Due to an increase in bot activity on the platform, we require verify of your account.
Please log in via the link below:
• bit.ly/antibot_check
Verificated deadline - 12 hours. Failure to verify will result in restricted access.
Sincerely, Dev Support

‌‍