ChangelogBook a demoSign up

Define your schema

AudienceData or analytics engineers, platform admins, technical marketers
Prerequisites
  • A connected data source (e.g., Snowflake, BigQuery, Databricks)
  • Technical understanding of your data and its relationships
  • Familiarity with Hightouch models (recommended)

This page covers how to create and configure schema models in Customer Studio. If you haven't decided on your grain, model topology, or naming conventions yet, start with Plan your data model.


What you'll learn

After reading this article, you'll know how to:


Overview

Before marketers can build audiences visually, data teams configure the schema in Customer Studio. The schema defines which models, relationships, and events are available in the audience builder.

In Customer Studio, you'll create:

  • Parent model: The base entity audiences are built from (for example, Users)
  • Related models: Additional context joined to the parent (for example, Households)
  • Event models: Timestamped behaviors (for example, Product Viewed)

Once configured, marketers can build audiences using warehouse data. If marketers need a reusable calculated value that isn't available as a column — like lifetime value or days since last purchase — create a trait.

Audience example


Create models

Define the parent model

The parent model is the core dataset for audience building — most commonly a Users table, but it could also be Accounts, Households, or Devices.

Before choosing a table, decide what one row should represent. This is your targeting grain — see Plan your data model for guidance.

Requirements:

  • One row per entity (for example, one row per user)
  • A stable, unique primary key (for example, user_id)
  • Fields useful for filtering (for example, email, region, created_at)

Create a parent model

  1. Go to Customer Studio → Schema.

  2. Click Create parent model.

    Create parent model

  3. Select a modeling method:

    • Table selector (default)
    • SQL query
    • dbt model
    • dbt Cloud model
    • Looker model
    • Sigma model

    Select modeling method

  4. Preview the results, then click Continue.

    Continue setup

  5. Configure the model:

FieldDescriptionExample
NameDisplay name in Customer StudioUsers
DescriptionContext for your teamRepresents end users of the platform
Primary keyUnique ID columnuser_id
Primary labelDisplay name in audience previewsfull_name or email
Secondary labelAdditional preview contextsignup_date

Column suggestions may be available depending on your workspace configuration. When enabled, they help marketers discover useful filter values in the audience builder.

  1. Click Create parent model.

    Configure model


Related models join to the parent via a foreign key and provide additional filtering context—like purchases, subscriptions, or devices.

Examples:

  • Households linked to People by household_id
  • Subscriptions linked to Companies by company_id
  1. Go to Customer Studio → Schema.

  2. Click the + icon next to your parent model.

  3. Select Create related model.

    Create related model

  4. Choose your table or modeling method and preview results.

Select related model

  1. Configure the relationship:
FieldDescriptionExample
NameRelated model nameHouseholds
DescriptionContext for marketersUser purchase records
RelationshipCardinality (1:many, etc.)1:many
Foreign key (join key)Column joining modelsuser_id

To match on multiple columns (for example, product_id and location_id), enable multiple join keys in the relationship configuration.

The primary key uniquely identifies rows. The join key connects tables.

  1. (Optional) If you want to add columns from the parent model onto the related model, turn on Merge columns.

  2. Click Create related model.

    Configure related model


Add event models

Event models represent timestamped behaviors like page views, logins, or checkouts. These power both real-time and historical audience logic.

Requirements:

  • At least one timestamp column (for example, created_at)
  • A foreign key linking to the parent model (for example, user_id)

Create an event model

  1. Go to Customer Studio → Schema.

  2. Click the + icon next to your parent model.

  3. Select Create related event.

    Create event

  4. Choose your table or modeling method and preview results.

  5. Click Continue.

    New event

  6. Configure the event:

FieldDescriptionExample
NameEvent nameProduct Viewed
DescriptionContext for marketersTracks user product views
Timestamp columnWhen the event occurredcreated_at
Event typeCategory (Generic, Checkout)Generic
Primary keyFor referencing or triggering Journeysevent_id
RelationshipCardinality to parent1:many
Foreign key (join key)Column joining event with parentuser_id

The primary key uniquely identifies a row. The join key links it to another model. Often, the primary key in the parent model becomes the join key in a related model, but they serve distinct purposes.

  1. (Optional) If you want to add columns from the parent model onto the event model, turn on Merge columns.

  2. Click Create event.

    Create event

If all events live in a single table, you can create multiple event models by filtering by event type (for example, Page View and Add to Cart).

Name events for marketers

Use a consistent, human-readable naming pattern. In most cases, Object + Verb works well because it groups related actions together in the audience builder:

  • Product Viewed, Cart Abandoned, Checkout Started, Subscription Renewed

Avoid names that expose implementation details instead of business meaning, like track_event_v2 or page_view_prod. If multiple events come from one event stream, split them into separate event models when marketers will think of them as different behaviors.


Configure columns

Use the Columns tab to control which fields appear in Customer Studio and how marketers interact with them.

  1. Open the model you want to update.
  2. Go to the Columns tab.

Columns tab in model configuration

Enable or exclude columns

Use the toggle next to each column to control whether it appears in Customer Studio.

Disable columns when:

  • the field isn't useful for filtering (for example, internal IDs)
  • the field adds noise for marketers
  • you don't want it available in audience filters

If a field is useful only for sync mappings or operational workflows, consider hiding it from the audience builder even if you keep it available elsewhere in the schema configuration.

Rename columns using aliases

Aliases control how columns appear in the audience builder.

For example:

  • geo_regionRegion
  • created_atSignup date

To set an alias, hover over the column and click the pencil icon.

Edit column alias

Set privacy levels for columns

Privacy levels control how column values appear in places like audience previews and profile exploration, while keeping the column available for filtering.

Use privacy levels for sensitive fields like:

  • email addresses
  • phone numbers
  • internal identifiers

Each column in the Columns tab has a Privacy dropdown. The default value is Unreviewed. Select the appropriate privacy level for each column based on its sensitivity.

Privacy level dropdown showing Blocked, Redacted, Sync-only, Sync-blocked, and Approved options

Set privacy levels before marketers begin building audiences. As a starting point:

  • Mark email addresses and phone numbers as Redacted if marketers need to filter on them but should not see raw values in previews.
  • Mark internal IDs as Sync-only or Sync-blocked when they are operationally useful but not meaningful for audience building.
  • Mark fields as Approved only when values are safe to display in previews and profile exploration.

If you're unsure, start more restrictively and loosen visibility later.

Configure case sensitivity

When enabled for your workspace, new string columns added to a schema model default to case-sensitive matching. This means filters like equals and contains in the audience builder distinguish between uppercase and lowercase values (for example, "Nike" and "nike" are treated as different values).

This applies to columns added after case-sensitivity was enabled for your workspace. Existing columns retain their previous behavior unless you update them.

If your audience filters depend on case-insensitive matching, review new columns and adjust settings as needed. Case sensitivity is configured per column in the Columns tab.

Columns tab showing the Case-sensitive toggle

Add descriptions and metadata

Aliases control how columns appear in the audience builder, but marketers also need to understand what values mean. Where possible, add descriptions in your modeling layer (for example, dbt column descriptions) so Customer Studio inherits business context directly. When that's not practical, use the description field on the model.

For columns that need extra context, document:

  • Allowed values for enums and status fields (for example, active, churned, trial)
  • Units for numeric fields (for example, whether amount is in dollars or cents)
  • Null behavior — whether null means unknown, not applicable, or genuinely missing
  • Boolean semantics — whether true is a raw data flag or derived logic

Enable filter value suggestions

Suggestions help marketers choose common values from a dropdown when filtering (for example, brands like Nike or Adidas).

As a rule of thumb, enable suggestions for columns with fewer than 100 distinct values — fields like region, plan_tier, or status. High-cardinality columns (for example, email addresses or order IDs) don't benefit from suggestions and add unnecessary compute during refreshes.

Suggestions are off by default to reduce query overhead. Enable them selectively where preloaded dropdown values help marketers build filters faster. You can control how often suggestions refresh from the model's Configuration settings. For most teams, a weekly refresh is sufficient once the schema is stable — schedule refreshes outside peak analytics hours when possible.

Refresh columns from your source

If you add or remove columns in your warehouse, you can refresh the columns available in the model.

  1. Open the model.
  2. Click the three-dot menu.
  3. Select Refresh columns available in source.

Refresh columns available in source


Define relationships

Use the Relationships tab to define how models connect in your schema. These relationships power cross-model filtering in the audience builder.

  1. Open the model you want to update.
  2. Go to the Relationships tab.

Relationships tab in model configuration

Relationship types

Relationships define how rows connect across models:

RelationshipUse when...Example
1:manyOne parent maps to many related recordsOne user has many purchases
1:1One parent maps to one related recordA company has one active subscription
many:1Many records map to one shared recordMany users belong to one household

Use 1:many for most behavioral data (for example, purchases, page views). Use many:1 when referencing shared entities like plans or organizations.

Validate before saving a relationship

Before saving any relationship, confirm the following:

  • Join keys use the same data type on both sides. A type mismatch (for example, integer on one side and bigint on the other) can cause silent join failures.
  • The relationship reflects the actual business cardinality, not just whatever setting lets it save. A 1:1 relationship on data that's actually 1:many produces wrong audience counts.
  • If using multiple join keys, every key pair must match for a row to join. A partial match returns no results.
  • After editing or recreating a relationship, re-check any dependent traits, audiences, or journeys that referenced it. Recreating a relationship generates a new internal ID, and existing references keep pointing at the old one until you update them.

Add a relationship

  1. Click Add relationship.
  2. Choose the relationship type (for example, 1:many or many:1).
  3. Select the model you want to connect to.
  4. Choose join keys for each model.
  5. Click Save.

Create a new relationship

Edit an existing relationship

To update a relationship:

  1. Go to the Relationships tab.
  2. Select the relationship you want to edit (for example, Purchase History).
  3. Update join keys, the connected model, or cardinality.
  4. Click Save changes.

Use multiple join keys

Multiple join keys let you match models on two or more columns. This is helpful when you need compound keys (for example, product_id and location_id).

Enable multiple join keys

  1. Open the model and go to the Relationships tab.
  2. Select the relationship you want to edit.
  3. Toggle Multiple join keys ON.
  4. Select the additional join key columns.
  5. Click Save changes.

Toggle multiple join keys

Merge columns across models

Merge columns let you surface fields from a parent model into a related or event model, so marketers can filter on those fields without switching models.

This is useful when:

  • the related/event model doesn't include marketer-friendly fields like region or plan name
  • you want to reduce duplication across traits or audiences
  • marketers need both behavior (events) and customer attributes in the same workflow

Merged columns appear as read-only copies in the target model and are filterable like native fields.

Merge column directionality

Merge columns copy fields from one side of a relationship into the other. Whether you can merge depends on the cardinality:

  • In a 1:1 relationship, you can merge in either direction.
  • In a many:1 relationship, you can merge columns from the 1 side into the many side — for example, merging Household columns into Users when many users belong to one household.
  • In a 1:many relationship, the merge toggle is not available. To merge in this direction, view the relationship from the other model where it appears as many:1.
  • The Merge columns toggle appears on the relationship configuration page. If you don't see it, check the cardinality — merge is only available on 1:1 and many:1 relationships.

Use merge columns for frequently used context that helps marketers filter more naturally — like adding region or plan_tier onto purchase records. Don't merge everything from adjacent models; keep it to fields marketers actually need in filters.

If a value only exists on a related or event model and you need it in sync field mappings, you have three options: merge it onto the parent, create a trait that rolls it up, or move the value upstream to the parent model directly.

Examples:

  • Users → Purchases — Merge geo_region from Users so marketers can filter Purchases by customer location.
  • Products → Product Viewed events — Merge brand or category from Products so marketers can build audiences based on product attributes.

Enable merge columns

  1. Open the model and go to the Relationships tab.
  2. Select the relationship you want to edit.
  3. Under Merge columns, toggle Merge columns ON.
  4. Choose the columns you want to merge, then click Save changes.

Merge columns toggle

If you don't see the merge columns toggle, check the relationship configuration and cardinality. Merge columns require a relationship where Hightouch can resolve a single value per row.

Through relationships

Use a direct relationship whenever two models can be joined directly. Use a through relationship only when the model you need is reachable only through an intermediate table. Through relationships are more brittle — if any link in the chain is deleted, recreated, or has its join key changed, the entire path can break without a clear error message.

Through relationships let you connect two models through an intermediate model (a linking table). This is useful for many-to-many scenarios.

Example: Users → Memberships → Subscriptions

  • Users join to Memberships on user_id
  • Memberships join to Subscriptions on subscription_id

This enables filters like "users with an active subscription" without duplicating logic.

Entity relationship diagram model

Set up a through relationship

Through relationships are configured in the Relationships tab of your parent model.

  1. Create the two direct relationships:

    • Users → Memberships (1:many)
    • Memberships → Subscriptions (many:1)

    Intermediate table

  2. Select your parent model, then open the Relationships tab.

  3. Click Add through relationship.

    Add through relationship

  4. Under Access, select the model you want to access (for example, Products).

    Select model

  5. In the through dropdown, choose the indirect path that connects your parent model to the target model (for example, PurchasesProducts).

    Choose path

  6. Click Save.


Label your models

Schema labels must be enabled by Hightouch. to turn it on.

Schema labels tell Hightouch what business entity each model represents, so the audience builder can use more intuitive language. When labels are applied, filters and insights adjust automatically — for example, a People-labeled parent model with a Household-labeled related model lets marketers build audiences using both individual and household-level data.

Label models based on the business entity they represent, not the warehouse table they came from:

  • People for individual users, leads, or contacts
  • Households for shared consumer entities
  • Accounts for companies or organizations

If a model could reasonably be interpreted in multiple ways, choose the label that best matches how marketers will use it in audience building. When you label a model as Households or Accounts, you'll also need to select a name column (for example, last name for households, company name for accounts).


Validate your schema

After creating your models and relationships, verify the schema works as expected before building production audiences.

Check primary key uniqueness

Each row in your parent model should have a unique primary key value. Duplicate keys cause audience membership to be evaluated multiple times for the same entity, leading to inflated counts and unexpected sync behavior. Run a quick query in your warehouse to confirm there are no duplicates:

SELECT primary_key_column, COUNT(*)
FROM your_parent_table
GROUP BY primary_key_column
HAVING COUNT(*) > 1

Confirm join key types match

Open each relationship and verify that the join key columns use the same data type on both sides. A type mismatch (for example, integer on the parent and bigint on the related model) can cause silent join failures. See Keep data types consistent for details.

Test with a simple audience

Create a small test audience using one or two filters and check that the results make sense:

  • Does the audience count match what you'd expect from a direct warehouse query?
  • Can you preview individual members and verify their attributes look correct?
  • Do filters on related and event models return the right subset of parent rows?

If counts are off, the issue is usually a grain mismatch or a misconfigured join key. See Troubleshoot schema issues for common causes.

Verify through-relationship chains

If you use through relationships, test each chain end-to-end. A change to any link in the chain (for example, deleting and recreating one of the intermediate relationships) can break the full path without an obvious error.


Troubleshoot schema issues

Audience counts are unexpectedly high or low

Cause: The parent model grain doesn't match what you expect. If the parent model is at the account grain but you expected user-level targeting, every qualifying account counts as one row — regardless of how many users belong to it.

Resolution: Open the parent model and check what one row represents. If the grain is wrong, switch the parent model to a user-level table or restructure the schema. See Choose the right grain for guidance.

Relationship setup fails with a type error

Cause: A mismatch between the primary key type on one model and the foreign key type on another. For example, an integer primary key on the parent and a bigint foreign key on a related model can cause join failures.

Resolution: Cast both columns to the same type upstream in your warehouse, then open the affected model and select Refresh columns available in source from the three-dot menu.

Traits or audiences break after schema changes

Cause: Renaming columns, changing join keys, or modifying relationships can break traits, audiences, or journeys that reference the old configuration. This is especially common after Git Sync updates that change relationship IDs.

Resolution:

  1. Go to Customer Studio → Schema and check the Activity tab on the affected model to see what changed.
  2. Open the broken trait or audience and update it to reference the current column or relationship.
  3. If the issue is a stale relationship ID (common after Git Sync changes), delete and recreate the relationship.

A field exists in the warehouse but doesn't appear in the audience builder

Cause: The column may not be added to the schema, may be disabled, or may be on a related or event model instead of the parent model.

Resolution: Check these in order:

  • Open the model, select the three-dot menu, and choose Refresh columns available in source.
  • In the Columns tab, check that the toggle for the column is on.
  • If the field is on a related or event model, it's available for filtering but won't appear directly in sync field mappings unless exposed as a merge column or trait. See Choose the right model type for guidance on where data should live.

Errors containing "failed to find direct relationship by ID"

Cause: A trait, audience, or journey references a relationship ID that no longer exists. This typically happens when a relationship is deleted and recreated (which generates a new ID), or after a Git Sync update changes relationship IDs.

Resolution:

  1. Open the affected trait or audience.
  2. Remove the filter or condition that references the old relationship.
  3. Re-add it using the current relationship from the schema.
  4. If the relationship was deleted, recreate it in Customer Studio → Schema first.

Errors containing "bad relationship data"

Cause: This family of errors means the relationship record exists but is inconsistent or incomplete. You may see variants like "bad relationship data, cycle detected," "bad relationship data, no rows returned," or "bad relationship data, no path." Common causes include a partial save that was interrupted, or a relationship that was modified without saving all required fields.

Resolution: Delete the broken relationship and recreate it from scratch. Verify the join key columns exist on both models and use the same data type before saving.

Cause: Through relationships depend on a chain of direct relationships. If any link in the chain is deleted, recreated, or has its join key changed, the through relationship can break without a clear error message.

Resolution:

  1. Open the parent model's Relationships tab and check whether the through relationship still shows the correct path.
  2. If the path is broken, delete the through relationship and recreate it after verifying both direct relationships in the chain are intact.

Upstream column changes aren't reflected in Customer Studio

Cause: Customer Studio doesn't automatically detect new or renamed columns in your warehouse.

Resolution:

  1. Open the affected model in Customer Studio → Schema.
  2. Select the three-dot menu and choose Refresh columns available in source.
  3. Update any column aliases if the underlying column name changed.

Manage your schema

Edit a model

To manage models in your schema:

  1. Go to Customer Studio → Schema.
  2. Select a model to open its details page.
  3. Use the tabs across the top to configure the model.

If your team uses Git for version control, you can manage your Customer Studio schema—including parent models, related models, event models, and relationships—using Schema Git Sync. Note that some UI-configured settings are not synced. See Git Sync limitations for Customer Studio schema for details.

Delete a model

  1. Open the model you want to remove.
  2. Click the three-dot menu, then select Delete.

Delete a model

Deleting a model removes it from the audience builder. Any audiences using it will break and must be updated.

Enrich match rates

Match Booster enhances match rates by enriching your schema with additional identifiers from Hightouch's identity graph.

  1. Open your parent model.
  2. Go to the Match Booster tab.
  3. Toggle Enable Match Booster.
  4. Select one or more identifier columns (for example, email or phone).
  5. Click Initialize Match Booster to start enrichment.

Match Booster tab

Learn more: Match Booster overview

Speed up previews with sampling

Sampling creates a smaller subset of your model data to improve performance when previewing audiences.

  1. Open your model.
  2. Go to the Sampling tab.
  3. Turn on sampling and configure the settings.
  4. Click Save & run sampling.

Learn more: Sampling

Sampling tab

Review model activity

Use the Activity tab to review recent changes and understand how a model is being used.

You can track:

  • recent updates to the model definition
  • audiences, traits, or syncs that reference the model
  • usage history for debugging and cleanup

Activity tab

Update model settings

Use the Configuration tab to manage core model settings such as primary key, preview labels, and column suggestion refresh interval.

Configuration tab

Column suggestion refresh interval

Hightouch can automatically refresh filter suggestions so dropdown values stay up to date as your warehouse data changes.

  1. Open your model.
  2. Go to the Configuration tab.
  3. Under Column suggestion refresh interval, choose how often suggestions should update.

Column suggestion refresh interval dropdown

This setting controls how frequently Hightouch updates suggested dropdown values in the audience builder.

It does not affect:

  • live audience results
  • sync behavior
  • warehouse queries (these always use your source-of-truth data)

Refreshing columns updates the fields and dropdown values shown in filters. It does not change your warehouse data or audience results.


What's next?

After defining your schema, choose the next step based on your role.

If you're managing governance and delivery

Set up rules that control how data flows to destinations and how consent is enforced:

  • Destination rules Define sync behavior, privacy policies, and delivery restrictions per destination.

  • Subsets Apply destination-specific filters (for example, opt-outs) without changing core audience logic.

  • OneTrust Snowflake Native App Enforce consent policies using Snowflake-native integration with OneTrust.

If you need reusable calculated values

If marketers need values that aren't stored as columns — like total spend, days since last login, or most frequent category — create them as traits:

  • Traits Build reusable computed fields that appear in audience filters and sync field mappings.

For guidance on when to use a trait vs. keeping logic upstream, see When to model something as a trait.

If you're a marketer

Once the schema is in place, you can begin building audiences:

  • Audiences Use filters, traits, and events to define dynamic segments directly from your data.

Ready to get started?

Jump right in or a book a demo. Your first destination is always free.

Book a demoSign upBook a demo

Need help?

Our team is relentlessly focused on your success. Don't hesitate to reach out!

Feature requests?

We'd love to hear your suggestions for integrations and other features.

Privacy PolicyTerms of Service

Last updated: Jun 2, 2026

On this page

Was this page helpful?