A lifecycle model that knows the difference between a lead who converted and a lead who was never allowed to.
A lifecycle-stage and attribution architecture for Anchorpoint TMS, a fictional B2B fleet-management SaaS company — five controlled stages instead of HubSpot's full default set, two custom properties instead of a sprawling data model, and a qualification gate that correctly blocks even a high-intent form submission when fleet size or consent doesn't clear the bar. Built entirely on free-tier HubSpot, proven against five real test contacts pushed through the actual funnel mechanics.
The problem
Anchorpoint Software, Inc. sells Anchorpoint TMS — a transportation management platform for regional trucking and logistics carriers — through a content-led, sales-assisted motion: demo requests and gated guides from marketing, a human SDR qualification call, then an Account Executive. Marketing and sales disagreed on exactly one recurring thing: what a contact's Lifecycle Stage actually meant at any given moment, and whether someone who filled out the demo form twice but never answered a call should read the same as someone who'd had an actual sales conversation. As the company's second Marketing Operations hire — building on an existing tracking system and consent architecture from two prior projects — the brief was to make Lifecycle Stage and attribution data trustworthy enough that scoring and ROI work could be built on top of it later without re-litigating what each stage meant.
What I set out to build
- A lifecycle model with exactly as many stages as the business needs — not every HubSpot default, and not a blind five-stage copy of a generic funnel diagram.
- A data model that uses HubSpot's own default, automatic properties wherever they already cover the need, so the free plan's roughly 10-property budget is spent only on what's genuinely missing.
- Qualification logic that treats "submitted a high-intent form" and "actually meets our ICP" as two separate questions, with a controlled vocabulary recording why a contact passed or failed each gate.
- First-touch and latest-touch attribution that survives a contact's entire lifecycle without being silently overwritten by a later session.
- A regression policy that treats Lifecycle Stage as a permanent high-water mark, so a lost deal on an existing customer can never make the system forget they'd already bought.
How the pieces fit together
The system runs as two layers that only meet at two points: when a contact is created, and when a deal changes state.
Track A — Native & automated
HubSpot's own Lifecycle Stage automation (Settings → Objects → Contacts → Automate tab) drives every deal-triggered transition — SQL→Opportunity on deal creation, Opportunity→Customer on Closed Won — backed by a native guardrail that refuses to move a record backward.
Track B — List-reviewed & custom
Two purpose-built properties (Qualification Reason, Fleet Size) plus two Active Lists stand in for the Workflow engine the free plan doesn't include, carrying the one transition — Lead→MQL — that genuinely needs marketing judgment rather than a system rule.
Five controlled stages, each with its own entry condition:
Any identified contact, no qualification yet — the default for every new form submission or manually created record.
Meets ICP (20–500 trucks) and either requested a demo directly or crossed an engagement threshold — reviewed via two Active Lists, not a workflow.
An SDR has confirmed real fit on a call — the one transition this system deliberately never automates.
A deal exists — set automatically the instant one is created, even for a contact who skipped MQL/SQL entirely via a warm referral.
The deal was won — set automatically, and permanent: a later lost deal on the same contact can never undo it.
Stack
What's actually running
Data model — two properties, not twenty
Of the full candidate list a rigorous lifecycle-and-attribution model could need, only two didn't already exist natively: Qualification Reason, a controlled dropdown recording why a gate passed or failed, and Fleet Size, a Company-level number driving the ICP check. Everything else — the five Became-a-[Stage]-Date fields, Original/Latest Traffic Source, First/Recent Conversion — is a free, default HubSpot property that simply had to be found rather than built.
Native lifecycle automation, not a Workflow
With no Workflow engine on the free plan, SQL→Opportunity and Opportunity→Customer run on a single native setting most free accounts never discover: Settings → Objects → Contacts → Lifecycle Stage → Automate tab. It fires the instant a deal is created or won, and comes with a guardrail that never moves a record backward — Customer stays Customer even if a later deal on that same contact is lost.
The one gate that stays manual — and the lists standing in for a Workflow
Lead→MQL is the one transition deliberately left unautomated: it requires weighing fleet size and marketing consent together, which is exactly the kind of judgment a free account can't hand to a system rule. Two Active Lists carry that judgment instead — a same-day Fast Path for direct demo requests, and a weekly Slow Path for accumulated engagement — each gated on Fleet Size (20–500 trucks) and the account's actual Marketing Consent property.
A second list for a problem that would otherwise hide
A manually created contact — a warm referral, say — never has a tracked session, so Original Source stays blank forever unless someone actually checks for it. A third list flags exactly that: anyone at MQL or beyond with no Original Source on record, which is a data-quality problem worth surfacing, not a reporting quirk to ignore.
Proving it, not asserting it
Five test contacts, pushed through real HubSpot mechanics — not five contacts with properties typed in by hand — covering the positive path, two negative paths, the regression guardrail, the one accepted exception to the whole model, and attribution permanence.
1 — Full positive journey
Marcus Whitfield submitted the real demo-request form, cleared the MQL gate, passed his SQL call, had a deal created and won for him — and his Lifecycle Stage advanced automatically at every deal-driven step.
2 — Negative scenario: fails the SQL call
Priya Anand qualified for MQL on fleet size and a direct demo request, then failed the SQL call. Lifecycle Stage stayed at Marketing Qualified Lead — it never advanced to SQL — while Lead Status flipped to Unqualified and Qualification Reason recorded the specific disqualification.
3 — Accepted exception: stage-skip via direct deal
Robert Tanaka was created manually and never ran through MQL or SQL. The moment an AE created a deal for him directly, Lifecycle Stage jumped straight to Opportunity — the one path this architecture deliberately allows to bypass the funnel, since a deal is itself proof of a real sales pursuit.
4 — Regression guardrail: import attempt
A CSV import tried to set Marcus Whitfield's Lifecycle Stage back to an earlier value after he'd already reached Customer.
5 — Regression guardrail: lost deal on an existing customer
A second deal was created on the same already-Customer contact and marked Closed Lost. Lifecycle Stage never moved — losing a new sale to an existing customer isn't the same thing as them never having bought in the first place.
6 — Attribution permanence
Original Traffic Source and Latest Traffic Source both populated and identical for a contact whose only visit was his original form submission — exactly the behavior the permanence rule predicts, verifiable down to the actual page URL in each Drill-Down field.
What I'd tell a hiring manager directly
Challenges
The most instructive snag wasn't lifecycle logic at all — it was two inverted filter operators ("is none of" instead of "is any of," "is unknown" instead of "is known") that kept three Active Lists silently empty for a full session before a direct, property-by-property comparison against a real test contact surfaced them. The second was discovering that HubSpot's "Recent Conversion" property stores a compound string, not a clean label, so an exact-match filter against it will never catch a real submission — only a "contains" filter does. Neither is a HubSpot limitation; both are the kind of mistake that building list logic by hand, instead of relying on a tested Workflow, makes easy to miss until you actually check the data on a real record rather than trusting the filter description.
Limitations
- Lead→MQL review is same-day at best (Fast Path) and weekly at worst (Slow Path) — a real Workflow on a paid plan would make this instant; free-tier Active Lists can't trigger anything on their own.
- HubSpot's native duplicate-management tool requires Professional or above; this project substitutes a documented manual search-before-create practice instead of a system safeguard.
- The underlying site and forms are shared with Project 2's Lumen Metrics build rather than rebuilt under Anchorpoint TMS's own branding, which is why some Recent Conversion values still reference the earlier project's name — cosmetic, but worth flagging rather than quietly hiding.
- This is an educational portfolio project, not a production CRM for a real company with a real sales team's judgment behind every SQL call.
What I'd build next
- Upgrade to a paid tier to replace the two Active Lists with a real Workflow, collapsing the same-day/weekly review gap to real time.
- Feed this lifecycle and attribution layer into a lead-scoring model, since Qualification Reason and the native engagement properties are already shaped for it.
- Build the ROI and revenue-by-source reporting this attribution layer was explicitly designed to support, once real deal volume exists to report on.
- Re-point the underlying forms and tracking at dedicated Anchorpoint TMS infrastructure instead of the shared Lumen Metrics site.