Skip to main content

Flow — Cold Outreach (Veterinary)

Status: DRAFTED Owner: john@veterinarywiseai.com Last verified against prod: 2026-05-04 (initial draft — not yet run end-to-end) Related skill: none (new vertical — no skill exists yet)


1. Purpose

Drive veterinary clinic prospects from first awareness to demo booking to paid setup. Source: scraped vet clinic listings. This is the second commercial non-church vertical. Pipeline mirrors church outreach but uses vet-coded copy and routes bookings to the vet-specific Cal.com event type.


2. Trigger

Same pipeline as church/funeral — parameterized by vertical = 'vet'.

  • Type: cron (weekly) + manual override
  • Source: /api/cron/outreach-scrape/route.ts (with vertical = 'vet' param)
  • Schedule: Scrape Mondays 6am ET; send Wednesdays 9am ET
  • Founder UI: /founder/[token]/outreach-engine → filter by vertical=vet

3. Preconditions

  • outreach_contacts row exists with vertical = 'vet', status = 'provisioned'
  • preview_url populated (must use vet preview template — NOT church or funeral template)
  • outreach_contacts.email_do_not_contact = false
  • outreach_contacts.status != 'dnc' and != 'bounced' and != 'converted'
  • tenant_voice_agents FK constraint DROPPED (Stream A — must be resolved)
  • Vet preview template deployed (Stream A)
  • RESEND_API_KEY active and domain verified for veterinarywiseai.com
  • Physical address confirmed in email footer template — BLOCKER for first send
  • Cal.com vetwiseai-demo event type exists (founder creates manually)

4. Steps

Step 1 — Scrape

What happens: Vet clinic listings are scraped from public directories and loaded into outreach_contacts with vertical = 'vet'.

Where: Scrape source TBD — likely Google Places API (veterinarian category), AVMA directory, or Yellow Pages vet category.

Verifications:

  • db: SELECT count(*) FROM outreach_contacts WHERE vertical='vet' AND created_at >= now() - interval '7 days' → >0 after scrape run
  • db: SELECT name, email, website FROM outreach_contacts WHERE vertical='vet' LIMIT 5 → spot-check: vet clinics only (no pet stores, no groomers)

Failure signal: Count doesn't grow → scraper blocked. Wrong business types included → filter criteria need tightening.


Step 2 — Provision (Personalized Demo Preview)

What happens: provision.ts scrapes the vet clinic website, generates vet-specific Q&A (species served, services, hours, triage scenarios), creates demo tenant row, populates preview_url.

Where: churchwiseai-web/src/lib/outreach/provision.ts — requires vet vertical path (FK blocker must be resolved)

Key Q&A to provision:

  • Species served (dogs, cats, exotic, equine)
  • After-hours emergency contact / preferred 24-hour facility
  • Common services (wellness, dental, surgery, emergency)
  • Appointment booking process

Verifications:

  • db: SELECT preview_url, status FROM outreach_contacts WHERE id = '<id>' → NOT NULL, status = 'provisioned'
  • render: GET {preview_url} → HTTP 200, vet template (not church or funeral), clinic name in title
  • render: Demo chatbot can answer "What species do you treat?" with provisioned answer

Failure signal: status = 'provision_failed' → FK constraint (Stream A). Preview uses wrong template → vertical routing broken.


Step 3 — Send Email 1 (Day 0)

What happens: Send Email 1 ("What happens when someone calls [Clinic Name] at 8pm?") via Resend. FROM: hello@veterinarywiseai.com.

Where: /api/cron/outreach-send/route.tscold-outreach-emails-vet.md templates

Verifications:

  • db: SELECT status, email_1_sent_at FROM outreach_contacts WHERE id = '<id>'email_1_sent, timestamp NOT NULL
  • render: FROM address is hello@veterinarywiseai.com, NOT churchwiseai.com or funeralwiseai.com
  • render: Subject: "What happens when someone calls [Clinic Name] at 8pm?"
  • render: ASPCA Poison Control (888-426-4435) mentioned correctly in body
  • render: No theological language ("church," "pastor," "prayer," "congregation")
  • render: CASL footer with physical address, unsubscribe link, source disclosure

Failure signal: FROM wrong → template not using VET_FROM constant. ASPCA number wrong → copy error, CRITICAL in this vertical.


Step 4 — Click → Preview Page

What happens: Prospect clicks demo link → /p/[token] stamps pro_website_clicked_at → 302 to /preview/[slug]?ref=outreach_{token}.

Verifications:

  • db: SELECT pro_website_clicked_at, status FROM outreach_contacts WHERE id = '<id>' → NOT NULL, status = 'clicked'
  • render: Preview page uses vet template — verify: "your clinic" not "your church," no cross/steeple, no congregation language, triage call-to-action visible

Failure signal: Church template showing → vertical routing broken in PreviewClient.tsx.


Step 5 — Chatbot Interaction (Demo)

What happens: Vet clinic owner/manager types symptoms or questions into demo chatbot.

Verifications:

  • render: Type "My dog ate chocolate, what should I do?" → AI gathers weight/amount, references ASPCA Poison Control, doesn't give a medical diagnosis, recommends appropriate action
  • render: Type "Do you treat cats?" → responds based on provisioned species data
  • render: Type "How do I schedule an appointment?" → clinic-appropriate response, not church booking language
  • code: AI does NOT claim to diagnose — it triages and escalates appropriately

Failure signal: AI gives medical diagnosis → CRITICAL. Contact John immediately. AI uses church language → vertical isolation broken.


Step 6 — Demo Voice Call (Optional)

What happens: Prospect dials demo number, hears vet-coded voice agent.

Verifications:

  • code: Greeting uses clinic name, mentions after-hours triage capability
  • code: Agent asks symptom questions, references ASPCA Poison Control for toxin cases
  • code: Agent does NOT say "Let me pray with you" or any church language
  • db: voice_call_logs row created with correct tenant

Failure signal: Wrong tone (enthusiastic instead of calm clinical) → vet prompt not applied. ASPCA not referenced on toxin call → CRITICAL escalation path broken.


Step 7 — Email 2 (Day 3) and Email 3 (Day 7)

What happens: Follow-up emails sent. Vet-coded copy only.

Verifications:

  • db: SELECT email_2_sent_at, email_3_sent_at FROM outreach_contacts WHERE id = '<id>'
  • render: Email 2 subject: "The 5pm Friday call that didn't go to voicemail"
  • render: ASPCA Poison Control number correct in Email 2 body
  • code: DNC gate blocks follow-up if outreach_contacts.email_do_not_contact = true

Step 8 — Reply / Book / Convert

What happens: Prospect clicks "Book a 20-min call" → cal.com/john-moelker/vetwiseai-demo. Booking recorded.

Verifications:

  • db: SELECT status, booked_at FROM outreach_contacts WHERE id = '<id>'booked, timestamp NOT NULL
  • code: Cal.com event type vetwiseai-demo exists before first campaign send

Failure signal: Cal.com event type missing → 404 on booking link. CRITICAL — check before first send.


Step 9 — Email 4 Break-Up (Day 14)

Verifications:

  • db: SELECT email_4_sent_at FROM outreach_contacts WHERE id = '<id>' → NOT NULL at day 14
  • render: Email 4 close: "Thanks for running a clinic that pet owners trust" — verify no church language

5. What the Recipient Sees

Email 1: Subject: "What happens when someone calls [Clinic Name] at 8pm?"

  • From: hello@veterinarywiseai.com
  • Practical-empathetic tone
  • CTA: "[HEAR [CLINIC NAME]'S DEMO →]" → vet-template preview page
  • CASL footer with physical address, unsubscribe, source disclosure

Preview page: /preview/[slug] — vet branded, demo chatbot with triage capability, "Book a Demo" CTA


6. Compliance & Unsubscribe

  • Regime: CASL (Canadian) + CAN-SPAM (US)
  • Unsubscribe: veterinarywiseai.com/unsubscribe?token={{token}}
  • DNC gate: outreach_contacts.email_do_not_contact = true
  • Physical address: Required — confirm with founder before first send
  • Source disclosure: "You're receiving this because [Clinic Name] appears in public business listings"

7. Failure Modes

FailureSignalAlerting path
FK constraint blocks provisioningprovision_failed statusStream A blocker
ASPCA number wrong in emailContent error — possible legal exposureManual review before first send
AI gives medical diagnosisCRITICAL — liabilityImmediate escalation to John
Preview uses wrong templateVisual QA failFix vertical routing
Cal.com event type missing404 on booking linkFounder creates manually before first send
FROM wrong domainDeliverability / brand mismatchFix VET_FROM constant

8. Verification Manifest

flow: cold-outreach-vet
verifications:
- step: 1
verb: db
command: SELECT count(*) FROM outreach_contacts WHERE vertical='vet' AND created_at >= now() - interval '7 days'
expect: ">0 after scrape run"
- step: 2
verb: render
command: "GET {preview_url}"
expect: "HTTP 200, vet template, clinic name in title, no church imagery"
- step: 3
verb: render
command: "Inspect email FROM, subject, body, ASPCA number, footer"
expect: "FROM=hello@veterinarywiseai.com, ASPCA 888-426-4435, CASL footer, no theology"
- step: 5
verb: render
command: "Type 'My dog ate chocolate' in demo chatbot"
expect: "Triage response, ASPCA reference, no diagnosis, appropriate escalation"
- step: 8
verb: db
command: SELECT status, booked_at FROM outreach_contacts WHERE id = '<id>'
expect: "booked, timestamp NOT NULL after Cal.com booking"

9. Open Questions / Known Gaps

  • Physical address for CASL footer — BLOCKER
  • Vet scrape source not finalized — confirm with founder which directory/API
  • tenant_voice_agents FK constraint — Stream A must resolve
  • Vet preview template — Stream A must ship
  • Cal.com vetwiseai-demo event type — founder creates manually
  • Resend domain verification for veterinarywiseai.com
  • ASPCA Poison Control fee disclosure: the ASPCA Animal Poison Control Center charges ~$95/case. The AI should reference it accurately — not imply it's free. Verify wording in triage prompts.
  • Species scope per prospect — provision.ts needs to detect clinic species scope from website before generating Q&A