HCC Docs

Running a campaign

Floor rules

Hooks can't change these. They're checked at the moment of dialing, whatever a hook said a while ago:

  • the Do Not Call list;
  • calling hours in the lead's timezone;
  • the audit row in dial_attempts;
  • pacing;
  • the recording notice.

A number on the list is kept out earlier too, when a lead goes in, whatever onLead said: the check at the dial is for a number listed since.

Pacing is a workspace setting, at most dialCps a second and dialConcurrent at once. You set those in Settings if you connected your own telephony account; on one we run for you, we set them, so ask us.

Hooks

  • onAnswer, on a queue target, decides what an answered call is. Return nothing and a held rep joins straight away. Return actions and they run, and a held rep goes free. call.enterFlow(flow, input?) hands the call to a flow, whose input is { lead } by default. A flow target takes the call itself.
  • afterCall is for side effects, such as logging to your CRM. It runs with retries when the rep files a disposition, or when wrap-up runs out, and sees outcome, repId, disposition, notes and any callbackAt. What it returns changes nothing: the sequence says what's next. It runs once per call, with the disposition if it's in by then.
  • A hook that keeps failing returns its leads, backs off, then pauses the campaign (pausedReason: 'hook_failing').

Parked leads

A lead parked as step_failed stays parked until someone looks. hcc.campaigns.retryLead(campaign, leadId) puts it back at the step it stopped at, within a minute. For a lead parked just after a call, that means another dial.

A .call handler that keeps failing for one lead holds that lead back and parks it after five tries, with lastOutcome: 'hook_failed'. It takes three different leads failing with none getting through to count towards pausing the campaign, so a handler that's down for everyone pauses it before the list parks.

Late dispositions

A rep can file a disposition after the wrap-up, for as long as it's their last call. If the lead already left on that call as exit or finished, your .goal still runs on it, and a callback time brings it back into the sequence. A lead taken out, or on Do Not Call, stays out.

Change the steps

Steps go by position, with an optional name that follows them: .call(sales, { name: 'second_call' }). hcc deploy warns when a change moves leads who are mid-sequence, and a lead whose step no longer exists parks as step_failed, with lastOutcome: 'step_missing'.

Test a campaign

Test a sequence with a clock you move:

const t = testCampaign(renewals);
const run = await t.start(t.lead());
await run.callEnded({ outcome: 'no_answer' });
t.clock.advance('30m');
await run.tick();