All Docs
FeaturesNurtureHubUpdated March 22, 2026

Referral & Advocacy Engine

Referral & Advocacy Engine

The Referral & Advocacy Engine automates outreach to existing clients at key lifecycle moments — tenancy renewals, sale completions, and contact anniversaries — to generate Google reviews, new referrals, and repeat instructions. No manual workflow setup is required.

How It Works

  1. Agents record contact outcomes via the existing outcomes system (e.g. renewed_tenancy, sold).
  2. The daily trigger scanner (runs at 04:00 UTC) detects qualifying outcomes and lifecycle events across all contacts.
  3. A 3-email referral sequence is generated by the existing Content Writer AI using the agency's brand profile and category-specific context.
  4. Agents review and approve the sequence via the existing email review UI.
  5. Sequences are delivered via the existing email delivery infrastructure.
  6. Agents record outcomes (review received, referral added, etc.) from the trigger log.
  7. The referral dashboard tracks aggregate performance over time.

Trigger Types

TriggerQualifying ConditionDefault Window
Tenancy Renewalactive_tenant contact with renewed_tenancy outcomeLast 7 days
Sale Completionactive_seller/buyer contact with sold or listed_property outcomeLast 7 days
12-Month AnniversaryContact assigned a category 11–13 months agoConfigurable

Suppression & Deduplication

Before firing a trigger, the scanner checks:

  • Email suppression list — suppressed addresses are skipped.
  • Marketing preferences — contacts who have opted out are excluded.
  • Recent trigger deduplication — the minDaysBetweenTriggers setting prevents a contact from receiving multiple referral sequences within a short period.
  • Active journey conflict — contacts already in a running journey are not triggered.

Referral Dashboard

Navigate to Dashboard → Referral & Advocacy (/dashboard/referral) to view:

KPI Cards

  • Sequences fired — total referral sequences generated in the selected period
  • Reviews received — count and review rate percentage
  • Referrals generated — new contacts attributed to referral campaigns
  • Repeat instructions — repeat business won through advocacy outreach

Breakdowns

  • Triggers by Type — sequences generated per lifecycle event type
  • Outcomes Breakdown — results recorded by agents (review received, referral added, repeat instruction, testimonial received, no action)

Recent Trigger Log

A table of the most recent trigger fires showing contact name (linked to contact profile), trigger type, contact category, and the date fired. Select a time period of 30, 90, 180, or 365 days.

Configuring Triggers

Navigate to Settings → Referral (/dashboard/settings/referral) to configure each trigger type independently.

Per-Trigger Settings

SettingDescription
EnabledToggle the trigger on or off for your organisation
Google Review URLLink included in review-request emails
Referral Form URLLink to your agency's referral submission form
Anniversary MonthsThe month window used for the 12-Month Anniversary trigger
Custom AI ContextAdditional context passed to the Content Writer for this trigger type

Changes take effect at the next daily scan.

Recording Outcomes

After a referral sequence is sent, agents record what happened via the trigger log:

OutcomeDescription
review_receivedClient left a Google or other review
referral_contact_addedA new contact was added as a referral
repeat_instructionClient re-instructed the agency
testimonial_receivedClient provided a written testimonial
no_actionNo response or follow-up action

Manual Trigger (Admin Only)

Admins can manually fire a referral sequence for a specific contact using the referral.triggerManual tRPC endpoint or via the contact profile (if surfaced in the UI). This is useful for contacts who were missed by the automated scanner or who should receive an out-of-cycle sequence.

tRPC API Reference

All endpoints are under the referral router and require an authenticated session. Endpoints marked admin only require the admin role.

referral.getConfig

Returns all three trigger configurations for the current organisation, with defaults applied where no config exists.

// No input required
const config = await trpc.referral.getConfig.query();

Response: Array of trigger config objects with fields: triggerType, enabled, anniversaryMonths, minDaysBetweenTriggers, googleReviewUrl, referralFormUrl, customAiContext.


referral.updateConfig (admin only)

Upserts a trigger configuration for the current organisation.

await trpc.referral.updateConfig.mutate({
  triggerType: "tenancy_renewal",
  enabled: true,
  googleReviewUrl: "https://g.page/r/your-review-link",
  referralFormUrl: "https://youragency.com/refer",
  minDaysBetweenTriggers: 180,
});

referral.listTriggerLog

Returns a paginated list of trigger log entries with associated contact details.

const log = await trpc.referral.listTriggerLog.query({
  limit: 20,
  offset: 0,
  daysBack: 90,
});
// log.items — array of trigger log entries
// log.total — total count

referral.recordOutcome

Records an agent-supplied outcome against a trigger log entry.

await trpc.referral.recordOutcome.mutate({
  triggerLogId: "<uuid>",
  outcomeType: "review_received",
  notes: "Left a 5-star Google review on 14 Jul",
});

outcomeType values: review_received · referral_contact_added · repeat_instruction · testimonial_received · no_action


referral.getStats

Returns aggregated performance statistics for the organisation.

const stats = await trpc.referral.getStats.query({ daysBack: 90 });
// stats.totals — { triggersFired, reviewsReceived, referralsGenerated, repeatInstructions, responseRate, reviewRate }
// stats.byTriggerType — [{ triggerType, count }]
// stats.byOutcomeType — [{ outcomeType, count }]

referral.triggerManual (admin only)

Manually fires a referral sequence for a specific contact.

await trpc.referral.triggerManual.mutate({
  contactId: "<uuid>",
  triggerType: "anniversary_12_month",
});

referral.listOutcomes

Lists recorded outcomes filtered by trigger log entry or contact.

const outcomes = await trpc.referral.listOutcomes.query({
  triggerLogId: "<uuid>",  // or
  contactId: "<uuid>",
});

Database Schema

Tables

referral_trigger_configs

One row per org per trigger type. Stores all per-trigger settings. Missing rows fall back to system defaults.

ColumnTypeDescription
iduuidPrimary key
orgIdtextOrganisation identifier
triggerTypeenumtenancy_renewal · sale_completion · anniversary_12_month
enabledbooleanWhether this trigger is active
anniversaryMonthsintegerMonth window for anniversary trigger
minDaysBetweenTriggersintegerMinimum days before re-triggering the same contact
googleReviewUrltextGoogle Review link
referralFormUrltextReferral submission form link
customAiContexttextAdditional context for Content Writer

referral_trigger_log

Immutable audit log. One row per trigger fire per contact.

ColumnTypeDescription
iduuidPrimary key
orgIdtextOrganisation identifier
contactIduuidLinked contact
triggerTypeenumTrigger that fired
sourceOutcomeIduuidOutcome record that caused the trigger (nullable)
journeyIduuidGenerated journey ID
firedAttimestampWhen the trigger fired

referral_outcomes

Agent-recorded results for each trigger log entry.

ColumnTypeDescription
iduuidPrimary key
triggerLogIduuidLinked trigger log entry
contactIduuidContact
outcomeTypeenumRecorded outcome
notestextOptional agent notes
recordedAttimestampWhen the outcome was recorded

Deployment Checklist

After deploying v1.0.87, run the following before enabling the feature for users:

# 1. Apply schema migrations
npx drizzle-kit push

# 2. Seed referral journey templates (12 templates, one per category)
npx tsx src/db/seeds/referral-journey-templates.ts

The trigger scanner will begin firing automatically at the next 04:00 UTC cron run. To activate triggers for an organisation, an admin must enable at least one trigger type in Settings → Referral.