Back to Heartbeat Blog

ATS fields for outreach metrics (copy/paste schema + field map)

0
(0)
February 3, 2026

What’s on this page:

0
(0)

54182

ATS fields for outreach metrics

Ben Argeband, Founder & CEO of Heartbeat.ai — Keep it plug-and-play; avoid vendor specifics.

What’s on this page:

Who this is for

This is for recruiting ops leaders who need consistent outreach reporting across an ATS, CRM, dialer, and email tool—without turning recruiters into data-entry clerks.

  • Recruiting ops building consistent reporting and definitions
  • TA leaders who need channel outcomes that tie back to pipeline stages
  • Teams cleaning up suppression, opt-outs, and deliverability before it becomes a brand issue

Quick Answer

Core Answer
Implement a minimum viable ATS field schema that separates contact truth from touch outcomes, so outreach metrics reconcile across email and calling tools.
Key Insight
Reporting breaks when “sent” is treated as “delivered” and opt-outs live in notes instead of contact-level suppression fields.
Best For
Recruiting ops building consistent reporting

Compliance & Safety

This method is for legitimate recruiting outreach only. Always respect candidate privacy, opt-out requests, and local data laws. Heartbeat does not provide medical advice or legal counsel.

Framework: “Clean data, calm recruiting” ops reality

TL;DR lookup: Store delivery/bounce/reply events in the email tool, call events in the dialer, and store suppression/consent/verification as contact truth in the ATS/CRM. Then roll up rates using consistent denominators.

Outreach reporting fails in predictable ways: different tools disagree, recruiters log outcomes differently, and leaders lose confidence in the funnel. “Clean data, calm recruiting” means you standardize a small set of fields that (1) protect deliverability and compliance, (2) make outcomes comparable across channels, and (3) are easy enough that reps will actually use them.

The trade-off is… you’ll capture less nuance in free-text notes, but you’ll gain metrics you can act on and defend across systems.

Step-by-step method

Step 1: Lock metric definitions (with denominators)

Before you build fields, lock definitions so your reports don’t drift by team or tool. Use these canonical definitions and always show the denominator:

  • Connect Rate = connected calls / total dials (e.g., per 100 dials).
  • Answer Rate = human answers / connected calls (e.g., per 100 connected calls).
  • Deliverability Rate = delivered emails / sent emails (e.g., per 100 sent emails).
  • Bounce Rate = bounced emails / sent emails (e.g., per 100 sent emails).
  • Reply Rate = replies / delivered emails (e.g., per 100 delivered emails).

Operational rule: delivery and bounce events come from the email tool. The ATS stores the resulting contact truth (suppression, opt-out, verification dates) so recruiters can’t accidentally re-contact suppressed records.

Step 2: Implement the minimum viable fields (MVF) first

These minimum viable fields are the smallest set that makes outreach metrics trustworthy and keeps you out of deliverability trouble:

  • Consent: status + source + timestamp
  • Opt-out / suppression: status + source + date + scope
  • Last verified date: email (and phone if you can)
  • Last touched date: by channel
  • Outcomes by channel: standardized picklists
  • Bounce type + bounce reason: hard/soft plus reason taxonomy
  • Wrong-person flag: plus corrected-contact workflow
  • Suppression source/date: always auditable

For the operational side of suppression, see suppression lists and opt-out management workflows.

Step 3: Separate contact truth from touch truth

Most teams mix “what’s true about the contact” with “what happened on one touch.” That creates overwrites and bad suppression decisions. Keep it clean:

  • Contact truth (persists): consent, opt-out/suppression, verification dates, wrong-person flag, preferred channel.
  • Touch truth (per activity): channel, timestamp, sender identity, template/sequence ID, outcome, bounce taxonomy (email), call disposition (dialer).

Step 4: Create a channel-agnostic Outreach Touch record

If your ATS supports custom objects, create an “Outreach Touch” object. If it doesn’t, simulate it with a structured activity record using required picklists. Either way, you need consistent fields across the CRM, dialer, and email tool so you can roll up metrics.

Minimum fields for each touch:

  • outreach_touch_id (unique)
  • contact_id (ATS contact/candidate ID)
  • job_id (if applicable)
  • channel (call/email/SMS/other)
  • touch_at (timestamp)
  • sender_user_id (recruiter)
  • sender_mailbox_id or sending_domain (for email)
  • outcome (standardized picklist)
  • outcome_at (timestamp)
  • template_id / sequence_id (if used)

Step 5: Add deliverability protection fields (bounce triage ladder worksheet)

When bounces spike, you need to act fast without guessing. Implement a bounce taxonomy and a logged action so ops can suppress, verify, refresh, or run authentication checks.

Uniqueness hook (worksheet): Triage ladder that prevents domain damage: bounce type → suppress/verify/refresh/auth check, plus copy/paste logging fields.

  1. Classify: bounce_category (hard/soft) + bounce_reason (invalid mailbox, domain not found, blocked/policy, mailbox full, rate limited, other).
  2. Decide action (log it): suppression_action_taken = suppress / verify / refresh / auth_check / none.
  3. Apply suppression (contact truth): opt_out_status + suppression_source + suppression_date + suppression_scope.

Visual note for your internal SOP: create a one-page “Bounce triage decision tree” that starts with bounce_reason and ends with the exact field updates to make in the ATS.

Step 6: Standardize outcomes so “no answer” means the same thing everywhere

Picklists beat free text. Keep the list short enough that recruiters don’t guess.

Channel Outcome picklist (copy/paste) Notes
Call no answer; left voicemail; gatekeeper; wrong number; connected (voicemail/IVR); human answered; scheduled follow-up; do-not-call request When “do-not-call request” occurs, set suppression_scope=phone_only and suppression_source=candidate_request.
Email sent; delivered; bounced-soft; bounced-hard; replied-positive; replied-neutral; replied-negative; auto-reply; unsubscribed/opt-out Delivery/bounce should be sourced from the email tool event stream.
SMS (if used) sent; delivered; failed; replied; opt-out Keep opt-out as contact truth in the ATS.

Step 7: Assign field ownership (auto vs manual) so logging actually happens

Recruiters will not maintain a complex schema manually. Decide what is auto-captured vs manually set, and who owns each field.

Field group Where it should be captured Capture mode Owner
Delivery events (delivered/bounced + reason) Email tool Auto Ops / systems
Suppression status + source/date/scope ATS contact record Auto when possible; manual allowed Ops policy; recruiters execute
Call dispositions Dialer + ATS touch record Auto from dialer; manual fallback Recruiters
Consent status/source ATS/CRM contact record Manual (structured picklist) Recruiters; audited by ops
Verification dates ATS contact record Auto from verification workflow Ops / systems

Step 8: Joining data for reporting (so your dashboard reconciles)

To make metrics reconcile, decide your join keys up front:

  • Primary join: contact_id + outreach_touch_id (best case).
  • If you don’t have a stable outreach_touch_id: join on contact_id + channel + touch_at (timestamp) within a tight time window, and treat it as a temporary bridge until you add a touch ID.
  • System-of-record rule: use the email tool for delivered/bounced/replied events; use the dialer for dials/connects/answers; use the ATS for suppression/consent/verification and for tying touches to pipeline stages.

This is how you avoid the classic argument where the ATS says “sent 500” and the email tool says “delivered 430” and nobody trusts either number.

Step 9: Build your copy/paste schema (field map + CSV-ready)

Below is a copy/paste schema you can hand to ops or your ATS admin. It’s vendor-agnostic and designed to map cleanly across an ATS, CRM, dialer, and email tool.

Diagnostic Table:

Use this to diagnose why outreach metrics don’t reconcile across systems.

Symptom Likely root cause Field(s) missing or inconsistent Fix (ops action)
Reply Rate looks “too low” in ATS vs email tool Replies counted against sent instead of delivered delivered outcome + delivered timestamp; reply outcome + reply timestamp Store delivered/replied as touch outcomes; report Reply Rate = replies / delivered emails
Recruiters keep emailing people who opted out Opt-out stored in one tool only; no contact-level suppression truth opt_out_status; suppression_source/date; suppression_scope Make suppression a required contact field in ATS; block sequences when suppressed
Bounce Rate spikes and nobody knows what to do No bounce taxonomy; no logged action; no owner bounce_category; bounce_reason; suppression_action_taken Use the bounce triage ladder; route auth_check to whoever owns sending domains
Call metrics don’t predict pipeline movement Dialer dispositions don’t map to human answers total_dials; connected_calls; human_answers; call_outcome Enforce definitions: Connect Rate = connected calls / total dials; Answer Rate = human answers / connected calls
Wrong-person contacts keep recycling into campaigns No wrong-person flag; no corrected-contact workflow wrong_person_flag; suppression_scope; refresh_task Set wrong_person_flag=true; suppress that email/phone; create a refresh task

Visual note for your internal SOP: keep a short “Postmaster checks” checklist for the person who owns sending domains (authentication alignment, reputation signals, and sudden list-quality changes).

Weighted Checklist:

Score your current schema before you rebuild it. Total 100 points. If you’re under 70, your metrics will be noisy and your deliverability risk is higher than you think.

  • (20) Contact-level suppression is explicit (status + source + date + scope)
  • (15) Consent/permission is captured (status + source + timestamp)
  • (15) Verification is captured (last verified date for email; last verified date for phone if available)
  • (10) Wrong-person handling exists (flag + suppression + refresh task)
  • (10) Touch outcomes are standardized across channels (picklists, not free text)
  • (10) Bounce taxonomy exists (hard/soft + reason)
  • (10) “Last touched date” is tracked by channel (prevents over-contacting)
  • (10) Reporting uses correct denominators (sent vs delivered; dials vs connected)

Nice-to-have: template_id/sequence_id on touches so you can isolate which messaging correlates with bounces, opt-outs, or replies without reading notes.

Outreach Templates:

These are internal ops templates (not candidate messaging). They reduce back-and-forth and make logging consistent across the ATS/CRM/dialer/email tool stack.

Template 1: Ops ticket to implement the field map

Subject: Implement ATS outreach metrics field schema (contact + touch)

Body: Please add the fields in the attached schema to our ATS and make them available for reporting exports. We need contact-level truth fields (consent, suppression/opt-out, verification dates, wrong-person flag) and touch-level outcome fields (channel outcomes + bounce taxonomy + template/sequence IDs). Deliverables: (1) fields created, (2) picklists configured, (3) required fields enforced on Outreach Touch records, (4) export/report view created, (5) documentation for auto-captured vs manual fields.

Template 2: Recruiter SOP snippet (what to log, when)

When you email: ensure the touch has channel=email and an outcome. Delivery/bounce should be auto-captured from the email tool. If you receive a reply, set outcome=replied-[positive/neutral/negative]. If the candidate opts out, set opt_out_status=true immediately.

When you call: log the call outcome. If a human answers, mark outcome=human answered (this drives Answer Rate). If it’s the wrong person, set wrong_person_flag=true and suppress that phone/email.

Template 3: Deliverability incident note (bounce spike)

Subject: Bounce spike triage (time window + sending domain/mailbox)

Body: We observed increased bounces. Please review bounce_reason distribution (hard vs soft; invalid mailbox vs blocked/policy). Actions: suppress hard bounces; verify/refresh questionable contacts; run authentication checks and review Postmaster signals. Log suppression_action_taken on the touch and suppression_source/date/scope on the contact.

Common pitfalls

1) Counting “sent” as “delivered”

This inflates denominators and makes Reply Rate look worse than it is. Store “sent” and “delivered” separately, and report Reply Rate as replies / delivered emails.

2) Opt-outs stored as notes instead of suppression fields

If opt-outs live in notes, they won’t block future outreach. Make suppression a contact-level truth field with source/date/scope so it’s auditable and enforceable.

3) Bounce type without bounce reason

Hard vs soft is not enough to act. You need a reason taxonomy to decide whether to suppress, verify, refresh, or run authentication checks.

4) Wrong-person isn’t treated as a data quality event

Wrong-person should trigger suppression of that specific email/phone and a refresh task. Otherwise it keeps recycling into sequences.

5) Overbuilding fields nobody uses

Start with the minimum viable fields. Add nice-to-have fields only after you see consistent logging behavior.

How to improve results

1) Build a weekly outreach health report (examples)

Don’t just show counts. Show rates with denominators, by recruiter and by sending domain/mailbox.

Example report columns (email):

  • sent_emails
  • delivered_emails
  • bounced_emails
  • replies
  • Deliverability Rate = delivered_emails / sent_emails
  • Bounce Rate = bounced_emails / sent_emails
  • Reply Rate = replies / delivered_emails

Example report columns (calls):

  • total_dials
  • connected_calls
  • human_answers
  • Connect Rate = connected_calls / total_dials
  • Answer Rate = human_answers / connected_calls

Measure this by… pulling delivery/bounce/reply events from the email tool, pulling dials/connects/answers from the dialer, and pulling suppression/consent/verification from the ATS contact record, then joining on contact_id and outreach_touch_id.

2) Use the bounce triage ladder to protect domains

When bounces rise, don’t guess. Classify by bounce_reason, take the logged action, and update contact-level suppression truth so the same bad address doesn’t get hit again.

3) Tighten verification and refresh cadence (without overpromising)

Verification fields let you stop arguing about “is this email good?” and start operating: if last_verified_email_at is stale, verify or refresh before you send. If you can’t verify, reduce risk by prioritizing contacts with recent verification and by suppressing repeated bounces.

Implementation Notes

Keep a one-page field map with: field name, object (contact/touch), type, allowed values, required?, source system (ATS/CRM/dialer/email tool), and reporting use.

For deliverability monitoring during incidents, review reputation and error signals in Google Postmaster Tools and align authentication settings as needed.

Legal and ethical use

Outreach data includes personal contact information and preferences. Treat suppression and opt-outs as first-class fields, not optional notes. Honor opt-out requests quickly, avoid contacting suppressed records, and document consent/permission where applicable. If you operate across regions, align your process with local data laws and your organization’s policies.

Evidence and trust notes

We publish how we define and audit outreach metrics so ops teams can compare apples-to-apples across tools. Start here: Heartbeat trust methodology and the deeper definitions page accuracy and metrics definitions.

Official deliverability references used in this playbook:

Related internal playbooks:

FAQs

What are the minimum viable fields I need to report outreach metrics in an ATS?

At minimum: consent status/source/timestamp, opt-out/suppression (status + source + date + scope), last verified date, last touched date by channel, standardized channel outcomes, bounce category + reason, wrong-person flag, and suppression source/date.

Where should bounce data live: ATS or email tool?

The email tool should be the system of record for delivery events (delivered/bounced and bounce reason). The ATS should store the resulting contact truth: suppression status, suppression source/date, suppression scope, and last verified date.

How do I keep call metrics consistent between a dialer and the ATS?

Standardize dispositions and report using fixed definitions: Connect Rate = connected calls / total dials; Answer Rate = human answers / connected calls. Store the call outcome on the touch record and roll up weekly.

What fields prevent repeated outreach to the wrong person?

Add a wrong-person flag at the contact level, suppress the specific email/phone that was wrong, and create a refresh task to find the correct contact. Don’t leave it as a note.

How do I protect deliverability when bounces spike?

Use a bounce taxonomy (hard/soft + reason) and a logged action field (suppress/verify/refresh/auth_check). Review authentication and reputation signals using Postmaster, and stop sending to known-bad addresses.

Next steps

  • Implement the minimum viable fields first, then enforce required picklists on Outreach Touch records.
  • Standardize reporting using the definitions in accuracy and metrics definitions.
  • If you want a workflow that includes ranked mobile numbers by answer probability, start here: create a Heartbeat account.

Appendix: CSV-ready field map (copy/paste)

Field Name Object Type Allowed Values / Notes Required? Primary Source
consent_status Contact Picklist unknown, implied, explicit, do_not_contact Yes ATS/CRM
consent_source Contact Picklist candidate_provided, referral, public_profile, prior_relationship, other Yes ATS/CRM
consent_at Contact DateTime ISO timestamp No ATS/CRM
opt_out_status Contact Boolean true/false Yes ATS (system of record)
suppression_source Contact Picklist candidate_request, bounce, internal_compliance, other Yes ATS
suppression_date Contact DateTime ISO timestamp Yes ATS
suppression_scope Contact Picklist email_only, phone_only, all_channels, domain_level Yes ATS
last_verified_email_at Contact DateTime Last time email was verified Yes Verification workflow
last_verified_phone_at Contact DateTime Last time phone was verified No Verification workflow
last_touched_email_at Contact DateTime Last email touch timestamp Yes Email tool
last_touched_call_at Contact DateTime Last call touch timestamp Yes Dialer
wrong_person_flag Contact Boolean true/false Yes ATS/CRM
outreach_touch_id Touch Text Unique ID Yes ATS/CRM
contact_id Touch Text ATS contact/candidate ID Yes ATS
job_id Touch Text Requisition/job ID (if applicable) No ATS
channel Touch Picklist call, email, sms, other Yes ATS/CRM
touch_at Touch DateTime ISO timestamp Yes ATS/CRM
sender_user_id Touch Text Recruiter user ID Yes ATS/CRM
sending_domain Touch Text Domain used to send the email (if applicable) No Email tool
outcome Touch Picklist Use the standardized outcomes table in Step 6 Yes ATS/CRM
outcome_at Touch DateTime ISO timestamp No ATS/CRM
bounce_category Touch Picklist hard, soft, none No Email tool
bounce_reason Touch Picklist invalid_mailbox, domain_not_found, blocked_policy, mailbox_full, rate_limited, other No Email tool
suppression_action_taken Touch Picklist suppress, verify, refresh, auth_check, none No ATS/CRM
template_id Touch Text Email template identifier No Email tool
sequence_id Touch Text Sequence/cadence identifier No Email tool

Note: This page is vendor-agnostic by design and does not assume or claim any native integration between systems.

About the Author

Ben Argeband is the Founder and CEO of Swordfish.ai and Heartbeat.ai. With deep expertise in data and SaaS, he has built two successful platforms trusted by over 50,000 sales and recruitment professionals. Ben’s mission is to help teams find direct contact information for hard-to-reach professionals and decision-makers, providing the shortest route to their next win. Connect with Ben on LinkedIn.


Access 11m+ Healthcare Candidates Directly Heartbeat Try for free arrow-button