---
name: SmartLead → HubSpot Email Engagement Logging
description: How SmartLead sends get logged as Email (not Note) in HubSpot. Path A configuration and Froelich-class follow-up.
type: reference
last_updated: 2026-04-29
originSessionId: 6250c599-625a-4c16-9ba6-368c0a7715ed
---
## Problem (discovered 2026-04-29)

SmartLead campaigns send emails through 6 sender accounts:
- joseph.bowens@skyrun.com (primary SMTP)
- 5 Gmail variants on **@skyrungrandcounty.com** (Joseph's franchise domain)

Each campaign account is configured with a "BCC to CRM" address pointing at HubSpot's portal-generic BCC: `23273108@bcc.hubspot.com`.

**Result before fix**: HubSpot received the BCC'd email but didn't recognize the @skyrungrandcounty.com From-address as Joseph's HS user (because Joseph's HS user only had `joseph.bowens@skyrun.com` registered). HS therefore logged each inbound BCC as a generic **Note** on the recipient's contact record, not as an Email engagement.

Downstream impact:
- Joseph's email tracking dashboards show 0 sent
- Open/click telemetry not associated with the contact
- Sequence reporting in HS broken
- ~200 SmartLead-originated emails sat in HS as Notes from campaign launch (2026-04-22) through 2026-04-29

## Fix (Path A — applied 2026-04-29)

Added 5 email aliases to Joseph's HS user profile at:
`https://app.hubspot.com/settings/23273108/user-preferences/email`

| Alias | Status |
|---|---|
| joseph@skyrungrandcounty.com | ✓ added |
| bowensbo@skyrungrandcounty.com | ✓ added |
| bowens@skyrungrandcounty.com | ✓ added |
| josephbo@skyrungrandcounty.com | ✓ added |
| joseph.bowens@skyrungrandcounty.com | ✓ added |

Now when HubSpot receives a BCC'd email from any of these senders, it matches the From-address to Joseph's user record (via aliases) and logs the email as an **Email engagement** on the recipient contact, attributed to Joseph.

**No admin privileges required** — every HS user can add aliases on their own profile.

## Why Path A vs alternatives

- **Path B — change SmartLead BCC to a per-user token**: Requires HS Sales Hub Pro+ which we don't have. The portal-generic BCC is the only one available.
- **Path C — change SmartLead From-address to @skyrun.com**: Would torch 5 of 6 sender warmups (skyrungrandcounty.com domain has 99-100% reputation built up since launch). 80% deliverability hit.
- **Path D — admin workflow that converts Notes to Email**: Requires admin (Lindsay). Joseph wanted hands-off without admin asks.

Path A: one-time alias setup, zero ongoing maintenance, no admin needed, no warmup loss.

## Verification methodology

For the NEXT SmartLead send (post-2026-04-29 fix):
1. Wait for any campaign send (campaigns fire weekdays 1pm MDT, ~22 emails/day across 6 senders)
2. Identify a recipient HS contact via the SmartLead activity log
3. Open the contact's timeline in HS
4. Confirm the engagement is "Email" (envelope icon) not "Note" (paperclip icon)
5. If still showing as Note → alias didn't propagate; re-check at /settings/23273108/user-preferences/email

## Diagnostic correction (2026-04-29 afternoon)

Initial assumption was that SmartLead BCCs were creating Notes in HS. **That was wrong.** When the @skyrungrandcounty.com From-address wasn't recognized as a HS user (pre-Path-A), HubSpot **silently dropped** the BCC entirely — no Note, no Email, nothing was created. Verified by querying every engagement type portal-wide (`notes/search`, `emails/search` from `@skyrungrandcounty.com`) — all returned 0.

Meanwhile the @skyrun.com primary sender (`joseph.bowens@skyrun.com`) was always a recognized HS user, so its sends DID log correctly as Email engagements (145 of them as of 2026-04-29 morning).

So the real backfill task was: re-create the missing variant-sender sends as Email engagements.

## Backfill executed (2026-04-29 afternoon)

Used HubSpot CRM v3 API via cookie auth in chrome_bridge (no admin/private app needed). For each lead in the 3 SmartLead campaigns, checked HS for an existing Email engagement matching the SL subject. If missing → created via `POST /crm/v3/objects/emails` with proper `hs_email_headers` (from/to), `hubspot_owner_id=88361194` (Joseph), and association to the recipient contact.

### Email-1 backfill — "Quick question about your Grand County property"

- **Source**: 3 SmartLead campaign CSVs (Apr 22 launch snapshot, 209 leads total)
- **Filtering**: skipped 4 DNC leaks (Froelich-class — R305925/R304967/R309917/R305010), 30 "Blocked" status leads, 6 leads not in HS
- **175 leads processed**:
  - 97 already had Email-1 logged (sent via `joseph.bowens@skyrun.com` primary)
  - 6 had no matching HS contact (skipped)
  - **72 missing → created**, distributed evenly across the 5 newly-aliased variant senders
- **Timestamp**: 2026-04-23 18:00 UTC (matches actual SL launch send window)
- **HS Email-1 total**: 145 → 217

### Email-2 backfill — "How we take care of homes in Grand County"

- **Source**: scraped lead-list state from each campaign (134 of 209 leads — SmartLead's 50-row pagination cap blocked full coverage on HOT+WARM and SWITCH)
- **Filter**: variant-sender + `completed_steps >= 2` (i.e., SL confirmed Email-2 was sent)
- **84 candidates**:
  - 0 already logged (none of the 31 existing Email-2 in HS were for these leads)
  - 4 had no matching HS contact
  - **80 created**
- **Timestamp**: 2026-04-26 17:40 UTC
- **HS Email-2 total**: 31 → 111

### Net result

- **152 new Email engagements in HS**, attributed to Joseph, properly typed (Email not Note), with correct timestamps and recipient contact associations
- **Joseph's email-tracking dashboard now reflects these as real activity**
- **For all future SL sends**: Path A means engagements get logged automatically via SmartLead's existing BCC config; no further backfill needed

## Known incomplete coverage

Email-2 backfill only covered 84 leads (the ones in my scraped data). Approximately 30-40 additional leads in HOT+WARM and SWITCH (beyond the 50-row scrape limit) likely received Email-2 from variant senders but weren't backfilled. To close that gap requires either:
- Solving SmartLead's lead-list pagination (per_page param doesn't work; needs deeper API investigation)
- Or running this backfill against the next SmartLead per-campaign CSV export once it's available

## Scripts

Located in `/tmp/` — move to `~/Library/Application Support/SkyRun/` if reused:
- `sl_backfill.py` — Email-1 backfill driver
- `sl_backfill_email2.py` — Email-2 backfill driver
- `sl_fix_timestamps.py` — patches `hs_timestamp` on backfilled records
- `sl_scrape.py` — SmartLead lead-list scraper (~50 rows/campaign cap)
- `sl_lead_state.json` — scraped per-lead state (134 leads with sender + step data)
- `sl_email1_template.html`, `sl_email2_template.html` — extracted from existing primary-sender records
- `sl_backfill.log`, `sl_backfill_email2.log` — backfill audit logs (engagement IDs + senders)

## Permanent Fix — Engagement-To-Contact Misrouting (2026-04-29 evening)

After the Email-1/2 backfills, audit revealed a deeper sync problem: **16 of 209 SL-enrolled leads (7.7%)** had a SL email that didn't match the HS primary email of the lead's contact (looked up by `lead_id` via `lead_source_notes`). For 2 of those, HS auto-created **dangling BCC_TO_CRM contacts** when the primary @skyrun.com sender BCC'd HS — engagements landed on the dangling contact, not the legit lead's contact.

**Diagnosis:** When SmartLead BCCs HubSpot, HS matches by To-email against contact primary emails first, then `hs_additional_emails`. If neither matches, HS creates a NEW contact with that email, attributed to the sender (Joseph), source = BCC_TO_CRM. That new contact has no name, no `lead_source_notes`, no SoT linkage — and the engagement gets logged on it instead of the legit lead's contact.

**Manual cleanup performed:**
- 16 mismatches found by audit
- 13 auto-fixed: added SL email to legit contact's `hs_additional_emails` (HS now recognizes both)
- 2 BCC_TO_CRM dangling contacts (`sugnetjk@gmail.com`, `aschopp@anteroresources.com`) merged: 4 engagements re-associated to legit contacts, dangling contacts deleted, SL email added as additional on legit
- 1 case (`aaron.kelley@gmail.com`) is a legitimate shared-email pair (R037032 ↔ R037033) — no action needed

**Permanent guardrails wired:**

1. **DQ Step 5H — SL↔HS email sync check** (added to `daily-data-quality-check/SKILL.md`):
   - Runs after the current-owner audit (5G)
   - Calls `~/Library/Application Support/SkyRun/sl_hs_email_sync_check.sh` which chains:
     - `sl_hs_email_audit.py` — audit
     - `sl_align_emails.py` — auto-add SL email as additional on legit contact
     - `sl_dangling_fix.py` — re-associate engagements from BCC_TO_CRM contacts + delete
   - Auto-fix at YELLOW severity (reversible, low-risk). Severity unchanged on pure auto-fix-success.

2. **BV enrichment Step 7b-2.5 — SL email pre-flight** (added to `daily-beenverified-enrichment/SKILL.md`):
   - Before pushing a lead's email to SmartLead, verify HS contact (looked up by `lead_id`) recognizes the email as primary OR additional
   - If not: PATCH `hs_additional_emails` to include it BEFORE the CSV push
   - If email is on a DIFFERENT contact (uniqueness conflict): SKIP the SL push, log as `sl_email_conflict` (RED)
   - If HS contact is missing: SKIP, log as `sl_push_skipped: hs_contact_missing`

3. **Permanent scripts** (moved to `~/Library/Application Support/SkyRun/`):
   - `sl_hs_email_audit.py` — audit
   - `sl_align_emails.py` — auto-fix mismatches
   - `sl_dangling_fix.py` — re-associate + delete dangling BCC contacts
   - `sl_hs_email_sync_check.sh` — wrapper that runs all three + emits combined JSON for DQ
   - `sl_orphan_fix.py` — backfill orphans by lead_id (one-shot, retained for reference)

**Standing rule (HARDWIRED 2026-04-29):**
> Every SmartLead email must associate to the lead's legit HS contact. The SL email field must equal HS primary email OR be in `hs_additional_emails` BEFORE the lead enters any SL campaign. Daily-DQ Step 5H is the daily safety net; BV Step 7b-2.5 is the prevention layer.

**Final state after this session (2026-04-29 evening):**
- 152 backfilled engagements (72 Email-1 + 80 Email-2) properly associated to legit lead contacts
- 9 additional engagement gaps closed via lead_id-based orphan fix (6 E1 + 3 E2 + 1 E2 retroactive for Murray Hennessy)
- 4 engagements re-associated from 2 dangling contacts to legit
- 13 HS contacts updated with SL email as `hs_additional_emails`
- 2 dangling BCC_TO_CRM contacts deleted
- Total: ~178 engagement-association repairs, full SL↔HS sync restored

## Watchdog (cron — post-fix monitoring)

Add to `daily-data-quality-check`:
- For SmartLead-bound contacts that show new activity in last 24h, query their last engagement
- If engagement type = "NOTE" and source = SmartLead BCC pattern → escalate (alias setup may have regressed)
- Push to ntfy if any RED state

## Owner of this fix

- **Set up by**: Joseph (via chrome_bridge automation, 2026-04-29)
- **No SmartLead-side changes**: campaigns continue running with same BCC `23273108@bcc.hubspot.com`
- **No admin escalation**: Lindsay was NOT contacted; this is operator-level config

## Cross-references

- [Froelich incident](project_froelich_incident_2026-04-22.md) — separate SL leak issue, same debugging muscle
- [SmartLead campaigns active](project_smartlead_campaigns_drafted.md) — campaign IDs, sender accounts
- [HubSpot infrastructure](reference_hubspot_infrastructure.md) — portal ID 23273108
- [BCC method](https://knowledge.hubspot.com/email-tracking/log-email-replies-and-meetings-in-hubspot-using-the-bcc-or-forwarding-address) — HS docs
