Skip to content

Lead Management

  1. Many businesses don’t manage leads very well.
  2. HoneyGrid loses the conversion signal after sending leads to customers.
  3. Ads can’t be optimized as well as they could with more conversion data.

This problem primarily affects:

  • HoneyGrid customers who struggle to grow and get a good ROI from their marketing campaigns because they fail to convert the leads we generate.
  • The leads who aren’t contacted right away or at all which is a bad experience.
  • HoneyGrid because we lose visibility into the lead lifecycle and cannot report deep-funnel conversions (Lead qualified, Appt scheduled, First visit completed) to the Ad Platforms. This lack of visibility makes it difficult to differentiate between bad leads and poor lead management.

Success: How do we know if we’ve solved this problem?

Section titled “Success: How do we know if we’ve solved this problem?”
  • Acceptance KPI - Leads created in HoneyGrid
  • Acceptance KPI - Lead interactions in HoneyGrid
  • Correlated KPI - Average time to contact leads
  • Performance KPI - Qualified lead rate
  • Performance KPI - Converted lead rate
  • Insight KPI - Loss reasons, Unqualified reasons
  • Core KPI - Cost per lead (CPL)
  • Core KPI - Customer acquisition cost (CAC)

HoneyGrid and advertisers will have better visibility into lead quality and conversion rate benchmarks.

HoneyGrid will report conversions to Google, Facebook, Yelp, and Nextdoor which will improve lead quality.

Advertisers will have a way to know and improve their conversion rate.

  • Users can see a list of new leads in HoneyGrid
  • Users can move new leads to qualified, scheduled, or close them as lost
    • Loss reason = Not qualified
    • Unqualified reasons = No response, Medicaid, Service not offered, Insurance out-of-network, Wrong number, Other
  • New leads that cannot be contacted within 30 days are automatically closed lost (create a workflow that sleeps for 30 days from lead creation and then closes the lead as lost if it’s uncontacted)
    • Loss reason = No contact
    • Unqualified reason = No contact
  • Users can move qualified leads to scheduled or close them as lost
    • Loss reasons = Lost contact, Scheduling difficulty, Price, Other
  • Qualified leads that go cold for 30 days are automatically closed lost (create a workflow that sleeps for 30 days from lead qualification and then closes the lead as lost if it’s uncontacted)
    • Loss reason = Lost contact
  • Scheduled leads must have appointments attached to them
    • Appointments are Orders that can be matched through integrated data
  • Users can see a list of all past HoneyGrid leads
    • Time to contact
    • Time to qualify
    • Outcome
      • Unqualified with reason
      • Lost with reason
      • Won with appointments
  • Users can see their conversion rate, average time to qualify, and average time to schedule
  • Users can see a breakdown of their loss reasons
  • Leads are automatically moved to scheduled or completed during matchback
  • Leads are automatically moved to scheduled when HoneyGrid receives an email notification about an appointment scheduled online
  • Phone leads are automatically moved to the correct status and conversion stage
  • What scope should this project include?
    • Data structures
      • Contact
      • Activity
      • Tags
    • Screens - Mark will find key screens and define
      • Lead list (add fields)
      • Lead details (add fields)
      • Nav structure update: Leads, HoneyGrid, Settings (with subnav)
    • Included:
      • View and interact with leads in the HoneyGrid UI
    • Not included:
      • Automation
  • How should we model Contacts / {{Object Name: Opportunities}} / {{Object Name: Order?}}
    • Can we label the opportunities differently for various industries?
      • Appt requests
      • Quote requests
    • Can we label the orders differently?
      • Appointments
      • Jobs
    • Should contacts be unique in our system?
      • Yes
  • Do activities fall within the Contact? Opportunity?
    • Required:
      • Contact
      • Activity type
      • Date-time (auto-generated)
    • Optional:
      • Opportunity => closed won
      • Order => set appointments
      • Content
        • Text
        • Files
  • What events should we count as conversions?
    • Contacted
    • Qualified
    • Scheduled appt (scheduled order)
    • Ordered (completed order)
  • How should we assign value to conversions?
    • There are two types of conversion values to consider — Those reported to the user and those reported to the advertising platform
    • Conversion value should be reported to users in terms of value to their business. Integration with CRM/PMS applications will make it possible to calculate a true ROAS for the business
    • More granular conversions provide better signals back to the advertising platform’s algorithms to optimize ad targeting. The raw values are not important, but relative values are. We can value conversions on a relative scale such as
      • Contacted = 1
      • Qualified = 2
      • Scheduled order = 5
      • Completed order = 10
  • What lead statuses should we support?
  • What is the conversion id for facebook?
  • How do we set up google tracking params to always get gclid?
  • How should the HoneyGrid nav/app be structured?
    • Leads
      • Left panel: Inbox
        • Layout: list? Like Remi’s Inbox
        • Fields: Name, status, last activity, location (if multiple locations)
      • Main content: Lead details and activity
    • Campaigns (future)
    • HoneyGrid
    • Media - Property of a location (future)
      • Add assets
        • Images
        • Videos
        • Copy
          • Headline
          • Description
          • Calls-to-actions
        • How would we handle media with location-specific things?
          • Merge tags - Dentist in {{city}}
      • Create an asset group
    • Settings
      • Locations
      • Users
      • Data sources
      • Connections
  • Can we record and transcribe the outbound calls?
  • How should we handle lead value?
  • What is a campaign?
    • Grid
    • Lead tracking - Phone numbers
    • External campaigns (Google, Facebook, USPS)
    • Landing pages
    • Assets
  • What screens are users going to land on?
    • Leadboard - Default anything that is not closed, paginated if necessary
      • Name (display, search)
      • Open/Closed - Contact status
      • Status (display) - Contact status?
        • New
        • Contacted
        • Qualified
        • Converted
      • Phone number (search)
      • Email (search)
      • Last activity type and date/time (display, filter)
      • Location (if multiple locations)
    • Lead details
      • All based on an ID
    • Inbox
      • Activity - New messages/interactions
  • How will we want to query this data?
    • Event-based
      • Harder for list-based queries if we get all the lead metadata
    • Status - Which column?
    • Source
    • Date/time
      • Time to contact
    • Contacted vs not
      • Contacted rate
    • Qualified vs not
      • Qualified rate
    • Closed vs open
    • Converted vs not (Conversion rate)
  • How can we keep reporting fast?
    • Pre-compute/cache
  • What layout is best for the lead details?
    • Kanban board - Based on Status column
    • Inbox
      • Left panel is a list of leads sorted by most recent activity
      • Last activity date and label
      • Tags
        • HoneyGrid vs Customer
        • 1st contact attempt, contacted, qualified
        • 1st contact attempt => 2nd contact attempt
    • Table
/**
A contact is a potential customer of the business.
*/
interface Contact {
id: string;
name: string; // DEFAULT: 'unknown';
email: string; // DEFAULT: '';
activities: Activity[]; // Any sort of interaction with the Contact. This could be a phone call, text message, email, etc.
opportunities: Opportunity[]; // For dental, this would be an appointment request. Over time, a contact may request multiple appointments
orders: Order[]; // For dental, this would be an appointment. Over time, a contact may have multiple appointments tied to multiple opportunities
tags: string[];
createdDate: string; // iso timestamp of the contact creation
updatedDate: string;
deletedDate: string; // iso timestamp when the contact was deleted
lastActivityDate: string; // iso timestamp of the last activity
lastOrderDate: string; // iso timestamp of the last order
lastOpportunityDate: string; // iso timestamp of the last opportunity
}
interface Order {
id: string;
orderDate: string; // iso timestamp of the order (e.g. dental appointment date)
value: number; // This can be populated by industry benchmark or integration with CRM/PMS system
notes: string;
opportunity: string; // reference to the opportunity that was created from this order
createdDate: string; // iso timestamp of the order creation
updatedDate: string; // iso timestamp of the order update
deletedDate: string; // iso timestamp when the order was deleted
verifiedDate: string; // iso timestamp when the order was verified with the customer's CRM/PMS system
}
interface Opportunity {
id: string;
sourceMedia: 'phone' | 'form' | 'online-scheduling' | 'email';
sourcePlatform: 'google' | 'facebook' | 'usps' | null;
status: 'new' | 'first-contact-attempt' | 'second-contact-attempt' | 'third-contact-attempt' | 'closed-lost' | 'scheduled';
isNewCustomer: boolean | null; // true = yes, false = no, null = not sure yet DEFAULT: null
campaign: string | null; // reference to campaign DEFAULT: null;
isBusinessHours: boolean; // Was the lead created generated during business hours for the location?
unqualifiedReason?: 'no-contact' | 'no-response' | 'medicaid' | 'service-not-offered' | 'insurance-out-of-network' | 'wrong-number' | 'other'
unqualifiedReasonDetail?: string; // If unqualifiedReason is 'other' give the user an input to describe why
createdDate: string; // iso timestamp of the opportunity creation
firstContactAttemptDate: string | null; // iso timestamp of first contact attempt DEFAULT: null
secondContactAttemptDate: string | null; // iso timestamp of second contact attempt DEFAULT: null
thirdContactAttemptDate: string | null; // iso timestamp of third contact attempt DEFAULT: null
contactedDate: string | null; // iso timestamp when contact was made for this opportunity DEFAULT: null
qualifiedDate: string | null; // iso timestamp when the contact was qualified for this opportunity DEFAULT: null
closedLostDate: string | null; // iso timestamp of closed lost event DEFAULT: null
closedWonDate: string | null; // iso timestamp of closed won event DEFAULT: null
gclid?: string; // Leads from Google will come with a gclid that we can use to report conversions back to Google
fbid?: string; // Leads from Facebook will come with a fbid that we can use to report conversions back to Facebook
yelpId?: string; // Leads from Yelp will come with a yelpId that we can use to report conversions back to Yelp
nextdoorId?: string; // Leads from Nextdoor will come with a nextdoorId that we can use to report conversions back to Nextdoor
value: number; // The amount the opportunity is worth. DEFAULT: 0. When contactedDate is set = 100. When qualifiedDate is set = 500.
}
type Activity = CallActivity | EmailActivity | TextActivity
interface BaseActivity {
id: string;
type: string;
direction: 'inbound' | 'outbound';
opportunity?: string; // reference to an opportunity, if there is one ongoing
createdDate: string;
}
interface CallActivity extends BaseActivity {
type: 'call';
callRecordingUrl?: string; // url for recording of initial inbound call
transcript?: string;
summary?: string;
}
interface EmailActivity extends BaseActivity {
type: 'email';
fromAddress: string;
toAddress: string;
text: string;
html: string;
}
interface TextActivity extends BaseActivity {
type: 'text',
from: string;
to: string;
text: string;
}
interface FormSubmissionActivity extends BaseActivity {
type: 'formSubmission';
}
  • (instruction) List current data/tables we’ll need
  • (instruction) Any modifications needed
  • (instruction) New data models/fields to create
  • (instruction) Basic storage approach
  • Contact / Lead / Opportunity (we need to decide the object model)
    • Type: Phone call, Lead form, Text message
    • Lead ID - I think we need a good way to connect ID fields and track all activity under one umbrella
      • Name
      • Phone
      • Email
      • Address?
    • Preferred communications: SMS, Email, Phone call
    • Are you a new patient?
    • Appointment reason
    • Appointment preference
    • Stage: New, Qualified, Scheduled
    • Result: Open, Won, Lost
    • Appointments
    • Loss reason
    • Unqualified reason
    • Lifecycle metadata:
      • Created by
      • Created at
      • Updated by
      • Updated at
      • Qualified by
      • Qualified at
      • Scheduled by
      • Scheduled at
      • Closed by
      • Closed at
  • Orders / Appointments
    • First name
    • Last name
    • Date and time
  • Activity?
    • Contact
    • Opportunity
    • Date and time
    • Description ie Call, Email, SMS
  • (instruction) Which users are we building this solution for?
  • (instruction) Which other users will be affected by this solution?
  • Advertiser
    • Owner - Probably won’t use the feature day to day but will want funnel reporting
    • Manager - Usage will both operational and reporting depending on the advertiser
    • Member - HoneyGrid and advertisers need someone to handle the leads. It’s hard to motivate these people to do a good job or care much about the results. We should have an easy UI for operational team members but be realistic about what kind of adoption we’ll see. This is why we’ll likely follow up with Lead management to offload/automate scheduling.
  • Partner
    • Consultant - Partners will want to know HoneyGrid’s overall performance and have tools to use that data to bring more advertisers to HoneyGrid.
    • Contractor
      • Graphic design - N/A
      • Copy - N/A
      • Ad buyer - N/A
      • Scheduler - N/A
  • HoneyGrid
    • Sales - We’ll want to get our performance data to the point we’re comfortable and proud talking about it and leading with it in sales. We can’t really do that right now. This will help us have the data to analyze and share with potential customers and partners.
    • Finance - Little direct effect.
    • Product - We are the main consumer of aggregate and advertiser-level funnel performance data. We don’t have a clear enough signal around conversion quality until we do this. We can follow up with Conversion signal once this project is finished.
    • Operations
      • Graphic design - Little effect.
      • Copy - Little effect
      • Ad buyer - Another main consumer of funnel performance data to optimize accounts.
      • AI agent - N/A
      • Scheduler - N/A
  • (instruction) New endpoints needed
  • (instruction) Modifications to existing endpoints
  • (instruction) Basic request/response structure
  • Contacts / Leads / Opportunities
    • Create
    • Update stage
    • Close
  • Orders / Appointments
    • Create
    • Update
    • Delete
  • (instruction) List screens to build/modify
  • (instruction) Key user interactions
  • (instruction) Critical user flows
  • Leads inbox
    • List of leads in the left rail
    • Lead details
    • Activity feed
    • Tags
    • Opportunity details
    • Order details
  • Lead details
    • Details
    • Listen to phone call
    • See email content
  • (instruction) High-level approach
  • (instruction) Major components to build
  • (instruction) Key libraries/services needed
  • (instruction) Any significant technical decisions
  • (instruction) Technical uncertainties
  • (instruction) Performance concerns
  • (instruction) Security considerations
  • (instruction) Dependencies on other work
  • (instruction) Must-have features
  • (instruction) Nice-to-have features
  • (instruction) What we’re explicitly not doing
  1. Lead ingestion 1.a. Receive phone call leads from CallRail (Nextdoor, Yelp, Google) 1.b. Receive leads from Go High Level form submissions (Nextdoor, Google) — Landing page per platform. Helps with attribution. Enables reflecting back to the user the platform they came from. — Leverage Cloudflare to track bot traffic and location of users landing on the landing page 1.c. Receive form submissions from Yelp 1.d. Receive phone calls from Patient Prism
  2. Lead storage 2.a. Store leads in Airtable — Finish Call Scoring workflow — Part of the Airtable schema needs to include the tagging information 2.b. Once schema is solid, also store leads in HoneyGrid database (Eduardo?)
  3. Lead reporting 3.a. Report offline conversions to Google Ads 3.b. Report offline conversions to Facebook 3.c. Report offline conversions to Yelp 3.d. Report offline conversions to Nextdoor 3.e. Report leads metrics to advertiser in HoneyGrid Dashboard (Eduardo)
  1. Lead management