offdataai
Sales & CRM · data model template

Multi-Source CRM & Sales EDW data model

Data Vault 2.0 raw vault for integrating multiple CRM/MarTech/CPQ sources into one customer data platform: hubs (account/contact/opportunity/product/campaign), links (account-contact, opportunity-account, a transactional opportunity product-line link with quantity/price/amount, contact-campaign), and satellites (account, contact PII, an opportunity stage effectivity satellite, product, campaign details, and account status). Hash keys and load metadata are generated by the DDL layer. For a Salesforce-native, all-cloud (Sales/Service/Marketing) vault, use the Salesforce Customer 360 (Data Vault 2.0) template.

A multi-source CRM & sales enterprise data warehouse modeled as a Data Vault 2.0 raw vault for integrating heterogeneous systems (CRM, marketing automation, CPQ, ERP) into one conformed, historized vault: account, contact, opportunity, product, and campaign hubs; relationship links plus a transactional opportunity-line link; and descriptive plus effectivity satellites — with the contact-data lineage (GDPR consent, access, erasure) that makes Data Vault attractive for customer data platforms. It is a Data Vault 2.0 raw vault: hubs for business keys, links for relationships and satellites for descriptive history, with hash keys and hash diffs generated in the DDL.

Data Vault 2.0Sales & CRMGDPRCCPASOX
16
tables
100
columns
14
relationships
7
PII columns

Opening the template creates a project with the ERD, platform-native DDL, a dbt project and documentation already generated (recommended platform: Snowflake). Edit it in plain English or on the canvas, then ship it to any supported warehouse.

Subject areas

hubslinkssatellitesreference

Design decisions

  • Hubs hold only CRM business keys

    Separating account_id, contact_id, and opportunity_id into hubs lets marketing automation, CPQ, and billing source systems attach without reworking existing structures — the core agility of Data Vault.

  • Transactional opportunity-line link

    Opportunity line items are immutable quote events, so the line link is insert-only and carries its measures (quantity, unit_price, amount) directly — no satellite needed.

  • Effectivity satellite for opportunity stages

    Pipeline stages move forward and backward over time; an effectivity satellite records the valid period of each stage for accurate as-of pipeline and conversion reporting.

  • GDPR-driven masking on the contact satellite

    Contact email is hashed and mailing address is restricted so the governance report flags sensitive identifiers; marketing_consent plus load_date + record_source give the lineage needed for consent and erasure handling.

Tables in the Multi-Source CRM & Sales EDW model

Every table with its grain, columns, types and keys. PK marks a primary key, BK a business key and PII a column classified as personal data, which gets a masking strategy by default.

Hubs (5)

hub_account

Grain: one row per unique hub_account business key

ColumnTypeKeys
account_idvarcharBK
load_datetimestamp
record_sourcevarchar

hub_contact

Grain: one row per unique hub_contact business key

ColumnTypeKeys
contact_idvarcharBK
load_datetimestamp
record_sourcevarchar

hub_opportunity

Grain: one row per unique hub_opportunity business key

ColumnTypeKeys
opportunity_idvarcharBK
load_datetimestamp
record_sourcevarchar

hub_product

Grain: one row per unique hub_product business key

ColumnTypeKeys
product_codevarcharBK
load_datetimestamp
record_sourcevarchar

hub_campaign

Grain: one row per unique hub_campaign business key

ColumnTypeKeys
campaign_idvarcharBK
load_datetimestamp
record_sourcevarchar

Links (4)

lnk_account_contact

Grain: one row per lnk_account_contact relationship

Which contacts belong to which account.

ColumnTypeKeys
account_hkbinary
contact_hkbinary
load_datetimestamp
record_sourcevarchar

lnk_opportunity_account

Grain: one row per lnk_opportunity_account relationship

Which account an opportunity is associated with.

ColumnTypeKeys
opportunity_hkbinary
account_hkbinary
load_datetimestamp
record_sourcevarchar

lnk_opportunity_product_line

Grain: one row per opportunity product line (non-historized link)

Transactional (non-historized) link — opportunity line items with measures.

ColumnTypeKeys
opportunity_hkbinary
product_hkbinary
line_idvarcharBK
quantityinteger
unit_pricedecimal
amountdecimal
currencyvarchar
load_datetimestamp
record_sourcevarchar

lnk_contact_campaign

Grain: one row per lnk_contact_campaign relationship

Which contacts were targeted by / responded to which campaign.

ColumnTypeKeys
contact_hkbinary
campaign_hkbinary
load_datetimestamp
record_sourcevarchar

Satellites (6)

sat_account_details

Grain: one row per account_hk per change

Account descriptive history.

ColumnTypeKeys
account_hkbinaryPK
load_datetimestampPK
account_namevarchar
industryvarchar
account_typevarchar
annual_revenuedecimal
employee_countinteger
billing_countryvarchar
owner_namevarcharPII
load_end_datetimestamp
record_sourcevarchar

sat_contact_details

Grain: one row per contact_hk per change

Contact descriptive history (PII).

ColumnTypeKeys
contact_hkbinaryPK
load_datetimestampPK
first_namevarcharPII
last_namevarcharPII
emailvarcharPII
phonevarcharPII
mobile_phonevarcharPII
job_titlevarchar
mailing_addressvarcharPII
marketing_consentboolean
lead_sourcevarchar
load_end_datetimestamp
record_sourcevarchar

sat_opportunity_status

Grain: one row per opportunity per stage change

Effectivity satellite tracking opportunity stage transitions over time.

ColumnTypeKeys
opportunity_hkbinaryPK
load_datetimestampPK
stagevarchar
forecast_categoryvarchar
probability_pctdecimal
effective_fromdate
effective_todate
is_activeboolean
load_end_datetimestamp
record_sourcevarchar

sat_product_details

Grain: one row per product_hk per change

Product descriptive history.

ColumnTypeKeys
product_hkbinaryPK
load_datetimestampPK
product_namevarchar
product_familyvarchar
list_pricedecimal
currencyvarchar
is_activeboolean
load_end_datetimestamp
record_sourcevarchar

sat_campaign_details

Grain: one row per campaign_hk per change

Campaign descriptive history.

ColumnTypeKeys
campaign_hkbinaryPK
load_datetimestampPK
campaign_namevarchar
campaign_typevarchar
channelvarchar
start_datedate
end_datedate
budgeted_costdecimal
actual_costdecimal
load_end_datetimestamp
record_sourcevarchar

sat_account_status

Grain: one row per account per status change

Account status satellite split out for its rate of change.

ColumnTypeKeys
account_hkbinaryPK
load_datetimestampPK
lifecycle_stagevarchar
health_scoreinteger
is_activeboolean
load_end_datetimestamp
record_sourcevarchar

Lookup tables (1)

ref_currency

Grain: one row per ISO currency

ColumnTypeKeys
currency_codevarcharBK
currency_namevarchar
minor_unitssmallint

Relationships

Each relationship is a foreign key on the first table referencing the second.

  • lnk_account_contact.account_hk → hub_account (many-to-one)
  • lnk_account_contact.contact_hk → hub_contact (many-to-one)
  • lnk_opportunity_account.opportunity_hk → hub_opportunity (many-to-one)
  • lnk_opportunity_account.account_hk → hub_account (many-to-one)
  • lnk_opportunity_product_line.opportunity_hk → hub_opportunity (many-to-one)
  • lnk_opportunity_product_line.product_hk → hub_product (many-to-one)
  • lnk_contact_campaign.contact_hk → hub_contact (many-to-one)
  • lnk_contact_campaign.campaign_hk → hub_campaign (many-to-one)
  • sat_account_details.account_hk → hub_account (many-to-one)
  • sat_contact_details.contact_hk → hub_contact (many-to-one)
  • sat_opportunity_status.opportunity_hk → hub_opportunity (many-to-one)
  • sat_product_details.product_hk → hub_product (many-to-one)
  • sat_campaign_details.campaign_hk → hub_campaign (many-to-one)
  • sat_account_status.account_hk → hub_account (many-to-one)

Related templates

All templates →
Start for $1

From requirements to AI-ready context, in one platform.

Describe your business in a conversation, start from a template or connect your own database. Your first model is ready in minutes.

Get startedBook a demo

Plans from $1/month · cancel any time