Skip to content
// Find drip messages that are due now, for leads still active. One item per message.
// "now" can be injected via the API ({"now": "..."}) so the schedule is testable.
const s = $('Settings (edit me)').first().json;
const viaApi = $('Drip Run API').isExecuted;
const body = viaApi ? $('Drip Run API').first().json.body ?? {} : {};
const now = body.now ? DateTime.fromISO(body.now) : DateTime.now();
const db = $getWorkflowStaticData('global');
const leads = Object.values(db.leads ?? {});
const byId = Object.fromEntries(s.listings.map((l) => [l.id, l]));
const money = (n) => '$' + Number(n).toLocaleString('en-US');

const TEMPLATES = {
  checkin: (l) => ({
    subject: `Any questions about ${l.property || 'the homes I sent'}?`,
    body: `Hi ${l.first_name},\n\nJust checking in: do you have any questions about ${l.property || 'the homes I sent'}? I'm happy to set up a showing or send more photos and details.\n\nBook a time: ${s.booking_link}\n\n${l.agent_name}\n${s.brokerage}`,
  }),
  listings: (l) => {
    const homes = l.match_ids.map((id) => byId[id]).filter(Boolean);
    return {
      subject: homes.length ? `${homes.length} homes you might like` : 'Homes that just came on the market',
      body: `Hi ${l.first_name},\n\n` + (homes.length
        ? `Based on what you were looking at, these could be a fit:\n${homes.map((h) => `• ${h.address}, ${h.city}: ${money(h.price)}, ${h.beds} bd / ${h.baths} ba\n  ${h.url}`).join('\n')}\n\n`
        : `New listings come up every week. Tell me your budget and must-haves and I'll send the best matches.\n\n`) +
        `Want to tour any of them? ${s.booking_link}\n\n${l.agent_name}\n${s.brokerage}`,
    };
  },
  last_chance: (l) => ({
    subject: 'Should I keep you on my list?',
    body: `Hi ${l.first_name},\n\nI haven't heard back, so I don't want to fill your inbox. Are you still looking, or should I close your file for now? A one-word reply is perfect.\n\n${l.agent_name}\n${s.brokerage}`,
  }),
};

const due = [];
for (const l of leads) {
  if (l.status !== 'active' || !l.email) continue;
  for (const d of l.drip) {
    if (!d.sent_at && DateTime.fromISO(d.due_at) <= now) {
      due.push({ key: l.key, step: d.step, to: l.email, agent: l.agent_name, ...TEMPLATES[d.step](l), dry_run: body.dry_run === true });
    }
  }
}
return due.map((json) => ({ json }));