Use Case
Track customers across every product you build
Most indie hackers run more than one product. Two tools, five tools, ten tools — each with its own user table, its own database, and its own definition of who a customer is. TinyCRM gives you a single place to see all of them at once, merged by email, with per-product status and custom data.
The problem
When you build and ship multiple products, customer data scatters. Product A lives in a Postgres database on Railway. Product B is on Supabase. Product C is a WordPress site with a WooCommerce orders table. Each product has its own notion of who a user is, what they've done, and what plan they're on.
The problem compounds when a single person uses more than one of your products. There is no easy way to see that alex@example.com is a paid customer on Product A, a free user on Product B, and signed up for the waitlist on Product C. Without a unified view, you have no idea which of your customers are your most valuable across the whole portfolio — and you have no single place to look them up.
Spreadsheets fill the gap temporarily, but they go stale the moment someone upgrades or churns and you forget to update the sheet. Copying rows between tabs is not a customer database. It is a liability — outdated data you can't trust and can't query.
How TinyCRM solves it
Create a project for each product in TinyCRM
Sign up at app.tinycrm.dev and create one project per product. Each project gets a unique API key. This is what tells TinyCRM which product each customer event belongs to.
Install the SDK in each product's backend
Run npm install tinycrm-sdk in each backend codebase. Initialize a TinyCRM client with that product's API key. The SDK is zero-dependency and under 2 KB — it adds nothing to your bundle.
Call identify() when a user signs up or logs in
In your sign-up handler or auth callback, call crm.identify() with the user's email, name, status, and any custom params. This fires one lightweight HTTP request to TinyCRM.
TinyCRM merges by email — one row per person, badges per product
If the same email arrives from two different API keys, TinyCRM creates a single customer row with two product badges. The customer's profile shows both products, their per-product statuses, and their per-product params side by side.
Same customer, two products
Both calls below use different API keys but the same email. In the TinyCRM dashboard, they resolve to one customer row with two product badges — no duplicate, no manual merge.
Product A backend (e.g. Next.js)
import { TinyCRM } from "tinycrm-sdk";
const crm = new TinyCRM({
apiKey: process.env.TINYCRM_KEY_PRODUCT_A,
});
// User signs up to Product A
await crm.identify({
email: "alex@example.com",
name: "Alex Chen",
status: "paid",
params: { plan: "pro", mrr: 29 },
});Product B backend (e.g. Express)
import { TinyCRM } from "tinycrm-sdk";
const crm = new TinyCRM({
apiKey: process.env.TINYCRM_KEY_PRODUCT_B,
});
// Same person signs up to Product B
await crm.identify({
email: "alex@example.com",
name: "Alex Chen",
status: "free",
params: { source: "twitter" },
});Result in TinyCRM dashboard
alex@example.com │ Alex Chen │ [Product A: paid] [Product B: free]
│ │ plan: pro, mrr: 29 │ source: twitterWhat you see in the dashboard
The TinyCRM dashboard is a single filterable table. Every row is a unique customer — identified by email. Each row shows which products that customer has touched, their per-product status, their last activity timestamp, and any custom params you attached.
Product badges per row
Each customer row displays colored badges for every product they appear in. At a glance you can see whether someone is in one product, two products, or all five.
Per-product status
Clicking a customer badge shows you that customer's status on that specific product — free, trial, paid, or churned — independently of their status on other products.
Per-product JSONB params
Every customer-project relationship stores arbitrary key-value data. Plan tier, MRR, referral source, role — anything relevant to that specific product relationship.
Filter by project
The table can be filtered to show only customers who appear in a specific product, or customers who appear in multiple products simultaneously.
Filter by status
Find all paid customers across any product, or all free users who haven't converted yet. Status filters work globally or per-project.
Last activity timestamp
Each customer-project tracks when they were last active. Call ping() from your app to keep this timestamp fresh without changing status or params.
Frequently asked questions
How does TinyCRM merge customers across products?
By email address. When you call identify() from two different products with the same email, TinyCRM creates one customer row and links both customer-project records to it. The email is the merge key — same email always means the same person.
Can I track different statuses per product?
Yes. Each customer-project relationship has its own status field (free, trial, paid, churned) and its own JSONB params object. A customer can be paid on Product A and free on Product B at the same time — both are visible on their unified profile.
How many products can I track?
Unlimited projects on the $9/month plan. There is no per-project fee and no limit on the number of projects you can create. Each project gets its own API key and appears as a badge on each customer row in the dashboard.
Do I need to install the SDK in every product?
Yes. You install the SDK once per product backend and give each installation its own project API key from TinyCRM. This is what lets TinyCRM associate each identify() call with the right product and build the per-product badges on the customer row.
See all your customers in one place
14-day free trial. $9/month after. Unlimited projects, unlimited customers.
Also see: Next.js integration guide · TinyCRM vs Notion · All use cases · Track customers across products