Skip to main content

Client Lifecycle

Document: Agency Deep-Dive 1/4
Status: Active
Last Updated: 2025-12-18

Overview

Agency clients move through a structured lifecycle from prospect to long-term partner. Each stage has specific triggers, actions, and success criteria.
┌─────────────────────────────────────────────────────────────────────────────┐
│                          CLIENT LIFECYCLE                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   PROSPECT → QUALIFIED → PROPOSAL → ONBOARDING → ACTIVE → EXPANSION        │
│                                                                              │
│   Signals:     Discovery    SOW        Kickoff     Delivery    Upsell       │
│   Duration:    1-2 weeks    3-5 days   1 week      Ongoing     Quarterly    │
│   Owner:       Sales        Sales      PM          PM          CS + Sales   │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Stage 1: Prospect

Entry Triggers

  • Inbound inquiry (website form, email, referral)
  • Outbound targeting (LinkedIn, cold email)
  • Store service product purchase
  • Platform user upgrade interest

Data Captured

-- Initial prospect data lives in audience_profiles
SELECT 
  ap.email,
  ap.company_name,
  ap.company_size,
  ap.job_title,
  ap.lead_score,
  ap.wtp_score
FROM audience_profiles ap
WHERE ap.lifecycle_stage = 'lead'
  AND ap.company_size IN ('11-50', '51-200', '201-500', '500+');

Qualification Criteria

SignalWeightThreshold
Company size25%11+ employees
Budget indicator30%$2K+/month capacity
Decision authority20%Manager+ level
Timeline15%Within 90 days
Pain clarity10%Articulated problem

Actions

  1. Discovery call scheduling (Calendly)
  2. Needs assessment questionnaire
  3. Initial audit proposal

Stage 2: Qualified Lead

Entry Triggers

  • Completed discovery call
  • Lead score > 60
  • Budget confirmed
  • Timeline confirmed

Discovery Call Framework

## Discovery Call Agenda (30 min)

### Intro (5 min)
- Quick intros
- Agenda confirmation
- Permission to take notes

### Current State (10 min)
- What automation/AI are you using today?
- What's working? What's not?
- Team size and structure?

### Pain Points (10 min)
- Biggest time sinks?
- What would 10x your output?
- What have you tried that failed?

### Next Steps (5 min)
- Propose audit or pilot project
- Timeline alignment
- Decision process

Qualification Output

interface QualifiedLead {
  company_name: string;
  primary_contact: {
    name: string;
    email: string;
    title: string;
  };
  pain_points: string[];
  current_tools: string[];
  budget_range: 'under_2k' | '2k_5k' | '5k_10k' | '10k_plus';
  timeline: 'immediate' | '30_days' | '60_days' | '90_plus';
  decision_makers: string[];
  competition: string[];  // Other vendors they're considering
  fit_score: number;      // 0-100
}

Stage 3: Proposal

Entry Triggers

  • Qualified lead with fit_score > 70
  • Budget and timeline aligned
  • Decision maker identified

Proposal Types

TypeTimelinePrice RangeDeliverables
Audit1 week$1,500-3,000Assessment report, recommendations
Pilot2-4 weeks$3,000-7,500Single automation, proof of value
Engagement1-3 months$7,500-25,000Full project with multiple deliverables
RetainerOngoing$2,500-15,000/moContinuous support and development

Proposal Structure

## Agency Proposal Template

### Executive Summary
- Problem statement
- Proposed solution
- Expected outcomes
- Investment summary

### Scope of Work
- Phase 1: Discovery & Audit
- Phase 2: Build & Configure
- Phase 3: Test & Launch
- Phase 4: Optimize & Support

### Timeline
- Week 1: [milestones]
- Week 2: [milestones]
- ...

### Investment
- One-time: $X
- Monthly retainer: $Y (optional)
- Payment terms

### Team
- Your PM: [name]
- Technical lead: [name]

### Next Steps
- Sign SOW
- Kickoff call
- Tool access

Database: Creating the Client

-- When proposal is accepted, create client record
INSERT INTO agency_clients (
  canonical_id,
  user_id,
  company_name,
  industry,
  company_size,
  primary_contact_name,
  primary_contact_email,
  monthly_retainer,
  is_active
) VALUES (
  'client_' || gen_random_uuid()::text,
  :user_id,  -- Link to their user account
  :company_name,
  :industry,
  :company_size,
  :contact_name,
  :contact_email,
  :retainer_amount,
  true
);

Stage 4: Onboarding

Entry Triggers

  • Signed SOW/contract
  • Payment received (deposit or first invoice)
  • Client record created

Onboarding Checklist

## Client Onboarding Checklist

### Day 1: Kickoff
- [ ] Kickoff call completed
- [ ] Project created in Linear
- [ ] Slack channel created (#client-[name])
- [ ] Client added to project management

### Day 2-3: Access
- [ ] Tool credentials collected (encrypted in agency_credentials)
- [ ] API keys provisioned
- [ ] Test connections verified
- [ ] Documentation shared

### Day 4-5: Discovery
- [ ] Current workflow documented
- [ ] Data sources identified
- [ ] Integration points mapped
- [ ] Success metrics defined

### Week 1 End: Alignment
- [ ] Project plan approved
- [ ] Timeline confirmed
- [ ] Communication cadence set
- [ ] First milestone scheduled

Project Creation

-- Create project for the engagement
INSERT INTO agency_projects (
  canonical_id,
  client_id,
  name,
  description,
  start_date,
  end_date,
  budget,
  status
) VALUES (
  'proj_' || gen_random_uuid()::text,
  :client_id,
  :project_name,
  :description,
  :start_date,
  :end_date,
  :budget,
  'active'  -- 'proposal', 'active', 'paused', 'completed', 'cancelled'
);

Secure Credential Storage

-- Store client credentials (encrypted)
-- Note: In production, use Supabase Vault
CREATE TABLE agency_credentials (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  client_id uuid REFERENCES agency_clients(id),
  
  service_name text NOT NULL,        -- 'shopify', 'instagram', 'mailchimp'
  credential_type text NOT NULL,     -- 'api_key', 'oauth_token', 'password'
  
  -- Encrypted fields (use pgcrypto or Vault)
  encrypted_value text NOT NULL,
  
  -- Metadata
  expires_at timestamptz,
  last_used_at timestamptz,
  is_valid boolean DEFAULT true,
  
  created_at timestamptz DEFAULT now(),
  updated_at timestamptz DEFAULT now()
);

-- RLS: Only agency admins can access
ALTER TABLE agency_credentials ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Agency admins only" ON agency_credentials
  FOR ALL USING (
    EXISTS (
      SELECT 1 FROM user_roles ur
      WHERE ur.user_id = auth.uid()
        AND ur.organization_id = (SELECT id FROM organizations WHERE type = 'agency')
        AND ur.role IN ('admin', 'editor')
    )
  );

Stage 5: Active Engagement

Delivery Workflow

┌─────────────────────────────────────────────────────────────────┐
│                    DELIVERY WORKFLOW                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   PLAN → BUILD → REVIEW → REVISE → APPROVE → DELIVER            │
│                                                                  │
│   Linear    Cursor    Client     Team      Client    Deploy     │
│   Ticket    Agent     Review     Update    Sign-off  + Docs     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Communication Cadence

TypeFrequencyFormatOwner
Status updateWeeklyAsync (Slack/email)PM
Check-in callBi-weekly30-min videoPM
Milestone reviewPer milestone45-min videoPM + Tech
Executive reviewMonthly30-min videoLead

Health Monitoring

-- Client health score calculation
CREATE OR REPLACE FUNCTION calculate_client_health(p_client_id uuid)
RETURNS integer AS $$
DECLARE
  health_score integer := 50;
  active_projects integer;
  overdue_deliverables integer;
  days_since_contact integer;
  revenue_trend numeric;
BEGIN
  -- Active projects (good)
  SELECT COUNT(*) INTO active_projects
  FROM agency_projects
  WHERE client_id = p_client_id AND status = 'active';
  health_score := health_score + (active_projects * 5);
  
  -- Overdue deliverables (bad)
  SELECT COUNT(*) INTO overdue_deliverables
  FROM agency_deliverables d
  JOIN agency_projects p ON d.project_id = p.id
  WHERE p.client_id = p_client_id
    AND d.due_date < current_date
    AND d.is_completed = false;
  health_score := health_score - (overdue_deliverables * 10);
  
  -- Days since last contact (bad if > 14)
  -- Would need a contact_log table for this
  
  -- Clamp to 0-100
  RETURN GREATEST(0, LEAST(100, health_score));
END;
$$ LANGUAGE plpgsql;

Stage 6: Expansion

Expansion Triggers

TriggerActionOwner
Project completing successfullyPropose next phasePM
Client mentions new pain pointDiscovery callSales
Usage hitting limitsUpgrade discussionCS
Quarterly review approachingPrepare expansion proposalPM
Referral opportunityAsk for introSales

Upsell Paths

Current Service → Expansion Options
─────────────────────────────────────
Audit Only     → Pilot project
Pilot Project  → Full engagement
One-time       → Monthly retainer
Single area    → Multiple verticals
Manual process → Managed service

Retainer Escalation

-- Track retainer history
CREATE TABLE agency_retainer_history (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  retainer_id uuid REFERENCES agency_retainers(id),
  
  change_type text NOT NULL,  -- 'increase', 'decrease', 'pause', 'cancel'
  from_amount numeric,
  to_amount numeric,
  
  reason text,
  effective_date date,
  
  created_at timestamptz DEFAULT now()
);

-- Retainer upgrade
UPDATE agency_retainers
SET monthly_amount = :new_amount,
    hours_included = :new_hours
WHERE client_id = :client_id
  AND is_active = true;

-- Log the change
INSERT INTO agency_retainer_history (retainer_id, change_type, from_amount, to_amount, reason, effective_date)
VALUES (:retainer_id, 'increase', :old_amount, :new_amount, 'Expanded scope to include video automation', :effective_date);

Churn Prevention

Warning Signs

SignalRisk LevelResponse
Missed meetingsMediumPM outreach
Delayed feedbackMediumEscalate to lead
Budget questionsHighValue review call
Competitor mentionsHighExecutive call
Unresponsive > 2 weeksCriticalSave call

Save Playbook

## Client Save Playbook

### Trigger: Client expressing concerns

1. **Acknowledge** - Don't get defensive
2. **Diagnose** - What's the real issue?
   - Deliverable quality?
   - Communication gap?
   - ROI unclear?
   - Budget pressure?
3. **Propose** - Solution options
   - Scope adjustment
   - Timeline extension
   - Price modification
   - Team change
4. **Commit** - Specific next steps
5. **Follow up** - Within 24 hours

Exit Process

-- When client churns
UPDATE agency_clients
SET is_active = false,
    churned_at = now(),
    churn_reason = :reason
WHERE id = :client_id;

-- Archive projects
UPDATE agency_projects
SET status = 'archived'
WHERE client_id = :client_id
  AND status = 'active';

-- Revoke credentials
UPDATE agency_credentials
SET is_valid = false
WHERE client_id = :client_id;

Metrics & KPIs

Client Metrics

-- Client lifetime value
SELECT 
  c.company_name,
  c.created_at as client_since,
  COUNT(DISTINCT p.id) as total_projects,
  SUM(p.budget) as total_revenue,
  AVG(p.budget) as avg_project_value,
  EXTRACT(days FROM (COALESCE(c.churned_at, now()) - c.created_at)) as days_as_client
FROM agency_clients c
LEFT JOIN agency_projects p ON c.id = p.client_id
GROUP BY c.id
ORDER BY total_revenue DESC;

-- Monthly recurring revenue
SELECT 
  SUM(monthly_amount) as mrr,
  COUNT(*) as active_retainers
FROM agency_retainers
WHERE is_active = true;

-- Client health distribution
SELECT 
  CASE 
    WHEN calculate_client_health(id) >= 80 THEN 'healthy'
    WHEN calculate_client_health(id) >= 50 THEN 'at_risk'
    ELSE 'critical'
  END as health_tier,
  COUNT(*) as client_count
FROM agency_clients
WHERE is_active = true
GROUP BY 1;

Funnel Metrics

StageConversion TargetAvg Duration
Prospect → Qualified40%7 days
Qualified → Proposal60%5 days
Proposal → Won35%10 days
Won → Active95%7 days
Active → Expansion50%90 days

Integration Points

With Platform

  • Platform users showing high usage → Agency upsell targets
  • Platform tier upgrades → Trigger CS outreach

With Publisher

  • Verticals needing custom content → Agency service opportunity
  • High-performing patterns → White-label for clients

With Store

  • Service product purchases → Auto-create agency project
  • Digital product buyers → Nurture to agency services

DocumentWhat It Covers
deliverables.mdWork products and templates
automation-packages.mdProductized services
reporting.mdClient dashboards
SCHEMA.mdAgency table definitions