Skip to Content
Data Model

Data Model

Every table and stream that enters Vendo is classified as one of a small set of entity types. These types define how data is stored, joined, transformed, and sent to destinations.

Think of them as the vocabulary Vendo uses before anything else happens — identity resolution, calculated properties, segments, attribution, and destination syncs all build on top of these entities.


The five entity types

EntityWhat it representsTypical sources
EventSomething that happened at a point in timeWeb tracking, Shopify orders, Stripe charges, email sends
UserA person or account record with traitsCRM contacts, analytics user profiles, Shopify customers
GroupA non-person entity with its own ID and propertiesCompanies, products, deals, CSV uploads, product feeds
Ad dataPlatform-reported advertising metrics by day/campaign/adGoogle Ads, Meta Ads, TikTok Ads, LinkedIn Ads
CustomWarehouse tables not yet classifiedBigQuery tables connected before entity mapping is configured

Once a custom table is mapped, it is promoted to event, user, group, or ad_data and behaves like any other entity of that type.


How the layers fit together

Layer 1 — Entities (this doc) event · user · group · ad_data · custom Layer 2 — Computed concepts Calculated properties · Segments · Custom metrics · Data Studio transformations Layer 3 — Destination outputs Audiences · Conversions (platform-specific shapes sent to ad tools and CDPs)

Layer 1 is raw, classified data. Layer 2 derives new fields and objects from Layer 1. Layer 3 renders computed results into the format each destination expects (for example, a Meta offline conversion payload or a Klaviyo audience list).

Audiences and conversions are not Layer 1 entities — they exist only at the destination side of the pipeline.


Events

An event is a time-stamped record of something that occurred: a page view, purchase, email open, subscription renewal, or any custom action you track.

Canonical fields

FieldRequiredDescription
event_nameYesName of the event (e.g. purchase, page_view, email_sent)
timestampYesWhen the event occurred
user_idNoActor who triggered the event. Some system or ad events have no user.
group_idNoGroup the event belongs to, if any (e.g. organization or account)
idempotency_keyNoProvider-supplied key used to deduplicate ingest
propertiesNoFree-form payload — amounts, product lists, UTM params, email body, etc.

What counts as an event

Vendo folds several legacy concepts into event:

  • Page views and custom track calls from Web Tracking and the Tracking SDK
  • Commerce events such as orders, checkouts, and refunds from Shopify or Stripe
  • Email messages — the message metadata and body live in properties
  • Revenue moments — purchase and charge semantics are expressed as events; aggregate revenue metrics are computed in Layer 2

Example

{ "event_name": "purchase", "timestamp": "2026-05-20T14:32:00Z", "user_id": "cust_abc123", "properties": { "order_id": "ord_987", "currency": "USD", "amount": 129.99, "products": [{ "sku": "SKU-001", "quantity": 1 }] } }

In the app

  • Browse event tables in the Data Catalog
  • Configure first-party collection under Data → Web Tracking
  • Map source columns to the event schema via semantic mappings on each source

Users

A user is a person-level record with stable identifiers and traits. After Identity Resolution runs, records resolve to a single Vendo profile ID (vendo_user_id).

Canonical fields

FieldRequiredDescription
user_idYesCanonical user identifier (resolved Vendo profile ID when available)
emailNoEmail address (PII)
phoneNoPhone number (PII)
first_nameNoGiven name
last_nameNoFamily name
organizationNoCompany or organization; may link to a group record
addressNoStructured postal address
custom_propertiesNoSource-specific traits (lifecycle stage, lead source, plan tier, …)
updated_atNoWhen the record was last updated

What counts as a user

  • User properties from analytics tools (Mixpanel, Amplitude, Segment)
  • CRM contacts from HubSpot, Klaviyo, Customer.io
  • Commerce customers from Shopify or Stripe
  • identify calls from Web Tracking that attach traits to a known ID

Contacts and user properties are the same entity in the current model — one user row per person, merged across sources by the identity graph.

In the app

  • View unified profiles under Data → Customers
  • Configure identifier mappings on the Identity Resolution tab
  • See resolved traits in Customer 360

Groups

A group is any non-person entity identified by a group_id and a type discriminator. Groups generalise what used to be separate concepts like company records, product catalog rows, and lookup tables.

Canonical fields

FieldRequiredDescription
group_idYesStable identifier for this group instance
typeYesKind of group — see common types below
nameNoHuman-readable label
custom_propertiesNoType-specific attributes
updated_atNoWhen the record was last updated

Common group types

TypeUse for
companyB2B accounts, organizations
productProduct catalog items, SKU feeds
dealCRM deals or opportunities
listStatic or uploaded reference lists
Custom slugsAny group type registered in your workspace

CSV uploads and warehouse tables that were previously treated as lookup tables are now registered as groups with an appropriate type.

Product feed destinations (Google Merchant Center, Meta catalog sync) consume groups where type = product.

In the app

  • Manage group types and instances under Data → Groups
  • Upload CSV reference data — it registers as a group with a chosen type
  • Map warehouse columns to the group schema via semantic mappings

Ad data

Ad data is platform-reported advertising performance: spend, impressions, clicks, and conversions broken down by date, campaign, ad set, and ad. It is structurally different from events — one row per day per ad entity, not one row per user action.

Canonical fields

FieldRequiredDescription
dateYesReporting date
campaign_idNoPlatform campaign identifier
campaign_nameNoCampaign display name
ad_group_idNoAd set / ad group identifier
ad_idNoIndividual ad identifier
spendNoAmount spent in account currency
impressionsNoImpression count
clicksNoClick count
conversionsNoPlatform-reported conversion count
attribution_keysNoUTM tags, click IDs (gclid, fbclid), geo — used to join ad data to events at query time

How ad data joins to events

Ad platforms do not share user-level click streams with your warehouse. Vendo joins ad data to events using attribution keys stored on both sides:

  1. Events carry UTM parameters and click IDs in properties or dedicated columns.
  2. Ad data rows carry the same keys in attribution_keys.
  3. Attribution models and reports use these joins to attribute conversions to channels and campaigns.

Typical sources

In the app

  • Connect ad platforms under Data → Apps
  • Review synced campaign tables in the Data Catalog
  • Use ad data in Reports, Optimization, and attribution transformations

Custom (unclassified)

Custom is a staging state for warehouse-connected tables that have not yet been assigned an entity type. It is not a permanent classification — every custom table should eventually be promoted.

When data is custom

  • You connect a BigQuery source or upload a CSV and have not finished semantic mapping
  • A table’s shape does not obviously match event, user, group, or ad data yet
  • You are exploring raw warehouse data before deciding how it fits the model

Promoting custom to a real entity

  1. Open the source in Data → Apps.
  2. Open Semantic mapping for the table.
  3. Choose the target entity: Event, User, Group, or Ad data.
  4. Map source columns to the canonical fields for that entity.
  5. Save and run a sync — the table is reclassified and participates in identity resolution, transformations, and destinations like any native source.

For groups, also select the group type (product, company, etc.) during mapping.


Entity relationships

┌─────────────┐ │ ad_data │ │ (by date/ │ │ campaign) │ └──────┬──────┘ │ attribution_keys ┌──────────┐ user_id ┌──────────┐ group_id ┌──────────┐ │ user │◄────────────│ event │─────────────►│ group │ │ (traits) │ │ (actions)│ │ (things) │ └──────────┘ └──────────┘ └──────────┘ ▲ │ │ identity graph │ └──────────────────────────┘
  • Events reference a user (who) and optionally a group (what account or product context).
  • Users accumulate traits from every source mapped as user.
  • Groups stand alone but can be linked from events and users.
  • Ad data joins to events for attribution; it does not replace event-level conversion tracking.

Legacy names you may still see

Vendo is consolidating an older eight-type model into the five entities above. During the transition, you may encounter legacy labels in older integrations or documentation:

Legacy termCurrent entity
eventsEvent
user_properties, contactsUser
group_properties, lookup_tableGroup
ad_dataAd data (unchanged)
email_messages, revenueEvent (semantics in properties or Layer 2 metrics)
customCustom (unclassified)
audiences, conversionsLayer 3 destination outputs — not source entities

New sources and mappings should always use the current entity names.


Last updated on