Skip to main content

Understanding Topics and Best Practices

Learn how to create Topics effectively and convert existing SQL into Topics for smoother data exploration with Zoë and the Explore page.

Updated over a month ago

A Topic is the foundation for data exploration — whether you’re starting from the Explore page or asking Zoë in chat. It represents a collection of tables (views) that are joined together using foreign keys. Topics define specific sections of your data model that belong together logically.


Topic Properties

type: (Required) The type of the file. For these topic files is should always be topic.

base_view: (Required) The base view of the topic. This is the name of the view you want to create the topic from.

model_name: (Required) The name of the model (e.g. database connection) the view references.

label: (Required) The label of the topic is what shows up to the end users of your data model. If not specified it defaults to the name of the topic.

description: This is the description of the topic. This is helpful to let business users know what data is referenced here.

zoe_description: The description of the topic shown to Zoë. If not set, Zoë uses description instead. If set, this replaces description for Zoë only. End users will still see description in the UI. Use this to provide context to Zoë on how to use the topic correctly.

hidden: A true indicates that this topic should be hidden in the user interface. If a topic is hidden it can still be referenced in the data model, despite not appearing to end users in the UI or to Zoë. The default is false which shows the topic in the UI.

required_access_grants: This is a list of access grant names that are required to access this topic.


Base View vs. Joined Views

A Topic must always have one base view — the focal point of the Topic. Other views can be joined as needed.

Example: A Standalone Topic

A simple Topic for user data:

type: topic
label: Users
base_view: users
model_name: my_model_name
description: This topic covers all available data at the user level.
zoe_description: Use this topic when asked about user data on its own.

Example: A Joined Topic

A Topic that includes Users and their Orders:

type: topic
label: Users with Orders
base_view: users
model_name: my_model_name
description: This topic includes user-level data and related order information.
zoe_description: Use this topic when asked about user data including orders.

views:
orders:
join:
join_type: left_outer
relationship: one_to_many
sql_on: ${users.user_id} = ${orders.user_id}

Explanation:

  • The base_view is users.

  • The orders view is joined using a left outer join, ensuring all users are included (even those without orders).

  • The relationship is one_to_many — one user can have many orders (primary key to foerign key)

  • sql_on defines the join condition.

Note: Only join views when it makes business sense. Zoë can query multiple Topics and merge results later, so you don’t need to combine everything into one Topic.


Translating SQL into a Topic

Let’s take a SQL query and convert it into a Topic:

SELECT
users.user_id,
users.user_name,
users.created_at AS sign_up_date,
orders.created_at AS order_date,
orders.order_id,
orders.product_id,
products.category,
SUM(orders.quantity) AS order_quantity
FROM users
LEFT JOIN orders ON users.user_id = orders.user_id
LEFT JOIN products ON products.product_id = orders.product_id
WHERE orders.created_at >= '2025-01-01'
AND products.category = 'Toys'
GROUP BY 1
ORDER BY 1;

How It Translates

  • The SELECT clause defines the columns for the analysis. You’ll select these in the Explore page or as Zoë to include in the query.

  • The FROM clause indicates the base view of the Topic.

  • The JOIN clauses indicate which tables to join into the Topic.

  • The WHERE clase represent filtering conditions set either in the Explore page as in the Chat.

  • The GROUP BY clause is automatically defined based on the selected dimensions (slices) and measures (aggregations).

Here’s what an equivalent Topic YAML would look like:

type: topic
label: Users Purchase Data
base_view: users
model_name: my_model_name
description: This topic includes user data, order details, and product information.
zoe_description: Use this topic when asked about user purchase or order data.

views:
orders:
join:
join_type: left_outer
relationship: one_to_many
sql_on: ${users.user_id} = ${orders.user_id}

products:
join:
join_type: left_outer
relationship: one_to_many
sql_on: ${orders.product_id} = ${products.product_id}

Final Thoughts

When designing Topics:

  • Keep them business-friendly — think about how analysts and Zoë will use them.

  • Use clear labels and descriptions.

  • Only include joins that add analytical value.

With these practices, your Topics will be easier to maintain and more intuitive for users and Zoë alike.

Fore more information on Topics, refer to the documentation.

Did this answer your question?