Scores computed in BigQuery don’t help your sales team if they stay in BigQuery. Reps work in Salesforce and HubSpot. Reverse ETL is the pattern for closing that gap: read from a dbt mart model, write to CRM custom fields.
This is sometimes called “data activation” — the idea that warehouse data only becomes useful when it reaches the operational systems where decisions get made.
The Architecture
The sync chain is straightforward:
- dbt builds the mart —
mrt__sales__lead_scoreswith the latest score, tier, and timestamp per lead - Reverse ETL reads the mart — on a schedule, or triggered after dbt runs
- Reverse ETL writes to CRM — maps columns to custom fields in Salesforce or HubSpot
The mart model you’re syncing should include at minimum:
lead_id(the primary key to match against CRM records)lead__score(numeric)lead__score_tier(hot / warm / cold)lead__score_updated_at(timestamp — lets you know when a score was last computed)- Optionally:
lead__score_breakdownif you want to show component scores in the CRM
In Salesforce, these map to custom fields on the Lead object: Lead_Score__c, Score_Tier__c, Score_Updated_At__c. In HubSpot, they map to custom contact properties with the same names.
Tool Landscape in 2026
Three tools dominate this space:
Hightouch — 250+ destination connectors, warehouse-native features (compute transformations inside the platform), splits, and audience builder on top of the sync. Pricing starts around $350/month. Best choice if you have complex activation needs beyond simple field syncing.
Census (now Fivetran Activations) — Fivetran acquired Census and folded it into their platform as “Fivetran Activations.” The free tier allows syncing up to 50 destination fields, which is enough for lead scoring if you’re not building complex audiences. The pricing model changed significantly with the acquisition — verify current terms before committing.
Polytomic — packages ETL and reverse ETL in one platform, which simplifies billing and eliminates the connector duplication between your inbound and outbound pipelines. Smaller connector library than Hightouch, but sufficient for standard CRM destinations.
All three can read from a BigQuery table or view, which means your dbt mart is a valid source without any additional setup. You point them at the model, map columns to CRM fields, and configure the sync schedule.
Sync Frequency
How often you sync depends on how quickly your downstream automation needs to react.
1–4 hours works for most sales operations use cases. Lead scores change because of behavioral signals (new page views, email opens, form submissions), and those signals accumulate over hours, not minutes. A score that was 42 (warm) this morning might be 85 (hot) by afternoon because a lead spent time on the pricing page. The 1-4 hour window means sales reps see an updated score when they sit down after lunch.
15–30 minutes is appropriate if you’re using CRM field changes to trigger marketing automation sequences. HubSpot workflows and Salesforce Process Builder / Flow can trigger on field value changes. If “lead score tier changes to hot” should trigger an immediate enrollment in an outreach sequence, you need shorter sync cycles to avoid the sequence firing hours after the trigger event.
Near-real-time (sub-5-minute) is rarely necessary for lead scoring specifically. Lead scoring is a model of cumulative behavior — it doesn’t need to be refreshed the instant someone clicks a link. Reserve near-real-time syncs for event-driven triggers where timing genuinely matters (e.g., abandoned cart signals in e-commerce).
Downstream CRM Automation
Getting scores into the CRM is the prerequisite. The value comes from what you do with them.
Common downstream automations once scores land in the CRM:
Auto-assignment. When Score_Tier__c changes to “hot”, assign the lead to a senior rep using Salesforce’s lead assignment rules. Remove manual triage from the process entirely.
Slack notifications. A webhook from the CRM to Slack notifies the assigned rep immediately when a lead enters the hot tier. The rep sees “Lead X just reached hot tier — they’ve been on the pricing page three times this week” in their Slack without checking Salesforce.
Nurture enrollment. When Score_Tier__c changes to “warm”, enroll the lead in a HubSpot sequence or Salesforce marketing email campaign. Don’t wait for a rep to manually add them.
Suppression. Leads in the “cold” tier for more than 60 days get suppressed from sales outreach but continue receiving marketing content. When their score rises (behavioral signals pick back up), the suppression lifts.
The pattern in all of these: the scoring logic lives in dbt where it’s version-controlled and testable. The CRM reacts to the output. Neither system needs to know how the score was computed — just what it is and when it changed.
What Doesn’t Belong in Reverse ETL
Reverse ETL is for pushing warehouse-computed attributes into operational systems. It’s not for:
Replacing the CRM as a system of record. The CRM owns contact and company data that your reps enter, qualify, and update. Don’t sync back CRM attributes you extracted to the warehouse — that creates circular data flows where you can’t tell which system has the authoritative version.
High-frequency event data. If you want click-stream events in the CRM, use a CDP (Customer Data Platform) or a direct integration, not reverse ETL from the warehouse. Syncing millions of events from BigQuery to Salesforce is expensive and slow.
Computed attributes that belong in the CRM natively. If HubSpot can compute “days since last email open” from its own data, let it. Save reverse ETL for attributes that only exist because of cross-system joins — the warehouse score that combines CRM data with GA4 data that the CRM can’t see.
Connection to the dbt DAG
The reverse ETL sync reads from the same dbt mart model that other downstream consumers use. The mart is the interface — dbt computes, the CRM consumes.
This separation matters for maintainability. When the scoring algorithm changes, you update dbt models. The reverse ETL configuration doesn’t change — it’s still reading from mrt__sales__lead_scores and writing to the same CRM fields. The CRM automation also doesn’t change — it’s still reacting to Score_Tier__c field values. The change is isolated to the warehouse layer.
For the full scoring pipeline that produces the mart model being synced here, see Rule-Based Lead Scoring in dbt and BigQuery ML for Lead Scoring.