Use Case

Segment customers with JSONB params

Every customer relationship in TinyCRM carries a free-form JSONB params field. Store plan tier, acquisition channel, role, MRR, trial dates — anything your product tracks. Filter the dashboard by any of it, instantly, at no extra cost.

The problem

You need segments. Traditional CRMs charge you for them.

Knowing who your customers are is not enough. You need to know which ones are on the paid plan, which ones came from ProductHunt, and which ones are admins versus regular users. That kind of segmentation is fundamental to running a product — not an enterprise feature.

Yet most CRMs treat custom fields as an upsell. You get a handful of standard fields on the free tier, and then you hit a wall. Want to track which acquisition channel a user came from? That's a custom field. Want to store their referral code? Another custom field. Want to flag which plan they're on? You're now in the paid tier of a tool that costs more per month than your product charges its customers.

For indie hackers building lean products, that model is backwards. Your data model is unique to your product. You should be able to define it yourself, not beg a CRM vendor for one more field slot.

The solution

How TinyCRM's JSONB params work

Every customer-project relationship in TinyCRM has a params field — a JSONB column in Postgres. You pass whatever object you want when calling identify(). TinyCRM stores it as-is and indexes it with a GIN index for fast key-value queries.

There is no schema to define upfront. There is no UI wizard to add custom fields. You simply pass the data that matters for your product, and it appears in the dashboard. When your data model changes, you just start passing different keys — old and new customers coexist with no migration required.

Because params are stored per customer-project relationship, not globally, the same customer can have completely different attributes in each of your products. Alice might be a pro subscriber in your newsletter tool and a free viewer in your analytics dashboard. Both are accurate; neither overwrites the other.

Examples

Useful params patterns

Plan tier + MRR

{ plan: "pro", mrr: 29 }

Filter to find all pro subscribers and sum their MRR without touching your database.

Acquisition channel

{ source: "producthunt" }

Segment customers by where they came from. Compare retention across channels.

Account role

{ role: "admin" }

Identify account owners versus regular users. Useful for reaching the right person during support.

Trial expiration

{ trial_ends: "2026-03-29" }

Store trial end dates and export customers whose trials expire this week.

Referral tracking

{ referral: "friend123" }

Track which referral code brought each customer in. Reward your top referrers.

Feature flags

{ beta: true, v2_ui: false }

Record which features a customer has enabled. Useful for correlating feature adoption with retention.

Code example

Passing rich params with identify()

Pass any object as params. TinyCRM stores it on the customer-project relationship and makes it filterable in the dashboard immediately.

Identify on sign-up with acquisition params

import { TinyCRM } from "tinycrm-sdk";

const crm = new TinyCRM({ apiKey: process.env.TINYCRM_API_KEY! });

// Called when a new user signs up
crm.identify({
  email: user.email,
  name: user.name,
  status: "free",
  params: {
    source: req.query.utm_source ?? "direct",
    referral: req.query.ref ?? null,
    signed_up_at: new Date().toISOString(),
  },
});

Update params when a customer upgrades

// Called from your Stripe/Paddle webhook handler
crm.identify({
  email: event.customer_email,
  status: "paid",
  params: {
    plan: "pro",
    mrr: 29,
    upgraded_at: new Date().toISOString(),
    billing_cycle: "monthly",
  },
});

// Dashboard filter: params.plan = "pro"
// → shows all 47 pro subscribers instantly

Frequently asked questions

What can I store in JSONB params?

Any key-value pairs: strings, numbers, booleans, and nested objects. Common examples include plan tier, MRR, acquisition source, role, referral code, trial end date, and feature flags. There is no predefined schema — you decide what to track.

Are params stored per-customer or per-project?

Per customer-project relationship. The same customer can have completely different params in different products. Alice might be { plan: 'pro' } in App A and { role: 'viewer' } in App B. Both are stored independently.

Can I filter the dashboard by params?

Yes. The customer table in the TinyCRM dashboard supports param-based filtering. You can filter by any key-value pair you have stored, making it easy to find all paid customers, all ProductHunt signups, or all users with a specific role.

Is there a limit on params size?

There is no hard limit on the number of key-value pairs you can store. The underlying storage is a Postgres JSONB column with a GIN index for fast queries. Store as many attributes as you need.

Start segmenting your customers today

14-day free trial. No credit card required. Custom fields included in every plan.