← Back to work
CASE STUDY · CRM · HACKATHON WINNER

Smart Tags: A Segmentation Engine That Never Goes Stale

Advisors were tagging households by hand into labels that were true the day they were applied and wrong a few months later. I designed and built Smart Tags — a rule-based tagging engine — solo, end to end, and won Savvy Wealth's company-wide hackathon, Big Bang 2026, with it.

PROJECT
A rule-based tagging and client-segmentation engine for financial advisors' CRM, plus a bulk CSV import wizard to onboard tags from other CRMs in one pass
ROLE
Product Design, Interaction Design, Full-Stack Build (Rails, GraphQL, React/TypeScript), Design QA
TOOLS
Claude Code, Conductor, GitHub, Vercel, Canny
GOAL
Turn tags from a static label advisors had to babysit into a rule that keeps itself accurate — and turn re-tagging an entire book of business into one action instead of hundreds

The problem: tags that lied

Visual context
V1 — Static tag
Household: Whitfield Age 30–40

Applied once, by hand. Never re-checked — six months later the client is 41 and still wearing a tag that's now a lie.

V2 — Smart tag
Household: Whitfield Age 30–40

Backed by a rule. Re-evaluates on every data change — the day the client turns 41, the tag removes itself.

Same tag, same household — the difference is what happens after it's applied. Reconstructed from the shipped rule engine, not a literal screenshot.

Tags shipped as static labels in December 2025. Advisors could apply a tag to a household, but nothing about it was true for long — client attributes like age, income, and last-contact date change constantly, and a label frozen at the moment it was applied starts rotting immediately.

"People aged 30 to 40. Well, your age changes, so eventually that tag is irrelevant. That's a filter, not a tag."

— Ed Wildermuth, Financial Advisor

"You go into each household, tag it, go to the next household, tag it — it's not good."

— Advisor feedback on bulk tagging

Two separate advisors, independently, named the same two failure modes: tags went stale, and applying them one household at a time didn't scale to a real book of business. That gave me a crisp brief — turn the existing Tags surface into a tagging and segmentation primitive, not a bigger pile of manual labels.

Why this, why now

  • Closed every "Done when" item already scoped in the backlog (Linear SV-888)
  • Shipped directly against advisors' top-requested Canny item — "Easier access to client tags" (score 8, ~45 addressable votes)
  • Became the segmentation primitive two other roadmap items were waiting on — Multi-Household Tasks and the Service Calendar could now reuse the same rule-based grouping instead of building their own
How it works · The rule engine

A rule you can trust, on both ends

Building a Smart Tag end to end — the rule, the overlap warning against an existing tag, and the tag re-evaluating live the moment a household's data changes.

A smart tag isn't just a label — it can be a rule: age, income, AUM, state, employment status, last-contacted date, and stage, combined with AND/OR logic in a visual builder I designed so advisors could write conditions without ever seeing a query language. The real design problem wasn't the builder's UI, though — it was trust. The live preview an advisor sees while building a rule had to match, exactly, what the system would actually do to their households afterward, or the feature would feel like a lie the first time it didn't. So I wrote the spec for how a rule evaluates once, then paired with Claude Code to implement it twice against that same contract — TypeScript for instant preview, Ruby as the source of truth — and tested both until they never disagreed.

When you save a rule, it applies right away across every household in the org instead of waiting on some overnight job — I wanted the effect to feel immediate, not theoretical. After that, any change to a household automatically re-checks its tags, and checking twice never causes problems: if nothing's changed, nothing happens.

How it works · Bulk CSV import

Turning "one household at a time" into one action

The other half of the bulk-tagging problem was advisors switching from Redtail or Wealthbox with years of tags already applied. Re-creating that by hand was the exact pain the advisor quote above was describing — so import needed to survive messy, inconsistent real-world exports without guessing wrong in either direction.

STAGE 1

Classify

  • Scores every column header and a sample of its cell contents — advisors never rename columns to match our schema
  • Each role (name, email, phone, tag) claims its best-scoring unclaimed column, so nothing double-assigns
  • Parses "Last, First" and "First Last" formats, drops suffixes like Jr./Sr./III
STAGE 2

Preview

  • Matches CSV rows to existing households on email, phone, and name, in tiers
  • A conflicting email/phone match is surfaced, not hidden — resolved in favor of email but flagged
  • Falls back to name matching only when no reliable contact info is on the row
STAGE 3

Confirm

  • Near-duplicate tag names auto-merge ("Stage is a Lead" ≡ "Stage is Lead")
  • An advisor's explicit rename always overrides the auto-merge
  • Smart tags can never be force-applied by an import — membership stays rule-governed

The full wizard, end to end — upload, classify, resolve the one ambiguous row, and land on 23 of 24 clients matched automatically.

The edge case that mattered most

A phone number can match the right household but the wrong person in it — a household's line might ring to Sophia, but the CSV row with that number is actually for Helen. If the name on the row doesn't align with the name behind the matched contact info, the row is pushed to a reviewable "ambiguous" queue with that household's other members offered as candidates — instead of silently tagging the wrong person because their sibling's phone number happened to match.

Iterating under a deadline

Shipping fast didn't mean skipping the polish pass

Hackathon timelines compress everything except the instinct to check your own work. Running a design-review pass against the finished build caught a consistency issue before submission — small on its own, but exactly the kind of thing that makes a feature feel unfinished.

Before
High Net Worth
Age 55–65
Recently Contacted
After
High Net WorthWealth Tier
Age 55–65Life Stage
Recently ContactedEngagement

The Zap icon that marks a smart tag was rendering the same way everywhere, regardless of which category the tag actually belonged to. Fixed to always inherit the tag's own category color, so the icon and the category agree everywhere it shows up.

Principles that held up

Automating trust, not just tagging

The hard part of this feature was never the rule builder UI — it was earning the right to let a system add and remove tags on its own without an advisor feeling like they need to double-check it. A few decisions did most of that work:

  • Smart tags are inviolable. Never manually removable, never a merge destination, never force-applied by an import — a rule-governed tag stays rule-governed, full stop.
  • Manual tags are never touched by automation. The system only ever changes what it created; an advisor's own tagging is never silently modified.
  • Ambiguity gets surfaced, not resolved quietly. A conflicting match is flagged and shown, not hidden behind a best guess.
  • AI refuses rather than hallucinates. The Claude-generated tag descriptions return empty on an ambiguous or nonsense tag name instead of inventing a plausible-sounding one.
Launch

Advisors using tags for client segmentation

An empty tags list is a hard sell, so launch didn't wait for advisors to build their first rule from scratch. A handful of high-need smart tags were created automatically for every advisor, existing and new, so the feature arrived with a few already working instead of a blank slate. Two mattered most: RMD Eligible, because a required minimum distribution deadline is one advisors genuinely can't afford to miss, and High Net Worth, because AUM is how advisors decide which households get their attention first.

Advisors with at least 1 tagged household 135of 207 advisors with a book
Average count of smart tags applied per advisor 12
Households tagged 3,593