Segmentation capability isn't built in the Braze dashboard. It's built upstream, in how your data is structured before it ever reaches Braze. Until teams really sit with that, they keep bumping into the same invisible ceiling.
Braze is a segmentation engine, not just a messaging tool
Most teams come to Braze thinking about sends: emails, push, in-app messages. Braze is excellent at all of that, but framing it as a messaging tool undersells what it actually is, which is a segmentation engine running on your data model.
What Braze can do for you depends on four things:
- User attributes - who your users are
- Custom events - what they've done
- Event properties - the context around what they've done
- Catalogs - non-user reference data that gives events meaning
A quick note on Catalogs because they show up a lot in this article. A Braze Catalog is a hosted lookup table of non-user data: product details, store locations, legal disclaimers, content metadata. You upload it (CSV or API), key each row to a stable ID, and reference rows in your messages via Liquid and selections to personalise content. To segment users by Catalog data (such as everyone who bought a product flagged category = "premium"), you reach for Catalog Segment Extensions, which join user behaviour against Catalog rows. Either way, the principle is the same: pass an ID through your events, keep the event payload small, and let the Catalog carry the richness.
A trap worth flagging: Catalogs are not data extensions
We've seen teams (often coming from an SFMC background) treat Catalogs as a general-purpose database, somewhere to dump user-level data, behavioural history, or anything they think they might want to query later. It's tempting because Catalogs feel relational and the dashboard makes them easy to upload to.
It's also a mistake. Catalogs are for non-user reference data. User-level information belongs in custom attributes or events. The moment you start storing user-keyed data in a Catalog you lose the segmentation Braze actually expects you to do, you create sync headaches between systems, and you build a foundation that breaks the moment you try to scale. Rule of thumb: if the data describes a person, it doesn't go in a Catalog.
The hidden cost of "good enough" data
A pattern we see across implementations: teams move fast to get campaigns live. Tracking gets bolted on quickly. Events get named inconsistently. Product data gets passed as loose strings. Nobody really thinks about what they'll need to query in six months.
It works at first. You can send basic lifecycle emails, trigger off simple events, and the dashboards look healthy. Then the program matures and the cracks show. Segmenting by product behaviour gets unreliable. Exclusion logic stops doing what you think it does. Personalisation breaks at scale. Canvases get more complicated as you build workarounds for missing fields, and the same logic ends up duplicated across canvases because the underlying data isn't clean enough to centralise.
Eventually you hit a hard ceiling, and the instinct is to blame the tool. But you haven't outgrown Braze. You've discovered you never really had a data model in the first place. You had a collection of tracking decisions that happened to work for a while.
A real (and destructive) example
We worked with a Quick Service Retail client where this pattern played out particularly badly. Purchase events were being ingested into Braze from their POS without a stable, governed schema. (A note in passing: the legacy purchase event is now being phased out in favour of Braze's eCommerce recommended events, but the structural lessons here apply either way.) The event structure had drifted over time, payloads were inconsistent across transaction types, and required properties (product IDs, store data, order metadata) were frequently missing.
On top of that, product names were coming through directly from the POS with no normalisation: thousands of them, full of duplicates, inconsistent naming, and entries that couldn't be reliably matched against the purchase events. Segmenting by product, category, or brand (some of the most commercially valuable targeting a QSR brand can do) was effectively off the table.
The downstream impact was real. Product-based segmentation didn't work. Liquid personalisation broke when expected properties weren't there. Revenue reporting in Braze was inconsistent. And cleaning up the product Catalog wasn't even possible the normal way: products couldn't be deleted because they were referenced by existing segments and campaigns, so they had to be blocklisted instead.
Because the data was fundamentally flawed and couldn't be fixed in place, the call was made to delete all historical purchase events and backfill clean data. That meant a temporary blackout (no purchase history flowing into Braze, no revenue data, no historical reporting) coordinated across Braze support, the client, the POS partner, and us. Not fun for anyone.
Where it usually goes wrong
Across multiple engagements, purchase and product data is where the worst structural problems concentrate. A typical "v1" looks like this:
{
"event": "purchase",
"product_name": "Running Shoes",
"category": "Footwear",
"price": "120"
}It fires. It shows up in Braze. It triggers a campaign. So teams move on. The problems compound:
- No consistent product ID, so you can't reliably reference the same product across events or systems
- Category is a free-text string - typos, capitalisation drift, and naming changes break filters silently
- Price is a string, not a number, so aggregations get unreliable
- No relationship between this event and any broader product Catalog
- Multi-product purchases collapse into a single flat event, so you can't reason about individual line items
Now try to build segments like "users who bought from category X but not store Y in the last 60 days," or "users who bought a low-margin product and haven't returned," or "users who browsed a specific SKU more than twice but never converted." You'll hit the limits almost immediately. And in retail or QSR, those are the segments that actually drive revenue.
The better approach: structured, relational data
The fix isn't complex, but it does need deliberate design upfront. A well-structured event looks more like this:
{
"name": "ecommerce.order_placed",
"time": "2024-01-06T02:46:00Z",
"properties": {
"order_id": "ORD-44219",
"currency": "AUD",
"total_value": 15,
"store_id": "139",
"store_name": "Flinders St",
"state": "VIC",
"products": [
{
"product_id": "MED_DRINK_1",
"product_name": "Medium Iced Latte",
"quantity": 1,
"price": 7.5,
"product_class": "Beverages",
"reporting_category": "Med_Size_Drinks"
},
{
"product_id": "PASTRY_3",
"product_name": "Almond Croissant",
"quantity": 1,
"price": 7.5,
"product_class": "Bakery",
"reporting_category": "Pastries"
}
]
}
}A quick note on which event to use - The legacy purchase event is being phased out. Braze announced the phase-out plans in 2026, in favour of eCommerce recommended events (ecommerce.order_placed, ecommerce.cart_updated, ecommerce.product_viewed, and so on). The eCommerce events are still in early access - speak to your CSM if you can't see them yet - but if you're implementing fresh today, that's where you should be heading. If you can't get to them yet, the same principles apply to any well-structured custom event in the meantime.
The other thing worth flagging about the v2 example: products live in a nested products array rather than at the top level. That's what lets you describe an order as a basket of multiple items rather than collapsing everything into one flat record.
The critical detail is product_id. Because each ID matches a row in a Braze Catalog, it acts as a foreign key: at message-time you can use Liquid to look up product metadata (category, brand, margin tier, promotional status, tags) without cramming it into the event itself, and at segmentation-time you can join behaviour to the Catalog through Segment Extensions. The event stays lean. The Catalog carries the detail. And because the Catalog is independently maintained, you can rename a category, add an attribute, or flag a seasonal promotion without touching the event schema or re-implementing tracking.
That separation changes what's possible. You can filter by any product attribute without changing your event schema. You can update product metadata without re-implementing tracking. Audience logic gets reusable instead of rebuilt every time, and multi-product orders become queryable at the line-item level via Segment Extensions, which can drill into nested event properties. This is when Braze starts to feel like it doesn't have a ceiling.
Identity is the other half of the foundation
Schema and identity are two halves of the same problem, but they often get treated separately. A perfectly structured event still falls apart if it isn't consistently attached to the right user. Users move across devices, authenticate at different points, and often exist as multiple profiles before they're merged. If your identity strategy (how you assign external_id, when you merge anonymous and known profiles, how you handle cross-device attribution) isn't deliberate, you end up with clean events attached to fragmented users.
The symptoms look like a data quality problem: segments that under- or over-count, personalisation pulling the wrong history, reporting that doesn't reconcile. If you're investing in restructuring your data model, the identity layer deserves the same scrutiny.
A practical framework
If you're planning a Braze implementation, or auditing one that's been live for a while, these principles consistently pay off:
- Think in relationships, not just events - Don't track actions in isolation. Model how data connects: users to products, products to categories, orders to campaigns. The richer the graph, the more powerful your segmentation gets.
- Standardise early and defend it - Consistent naming, stable IDs (especially for products and orders), predictable schemas. If product names are coming from a POS, normalise them before they reach Braze, not after.
- Separate behaviour from metadata - Events capture what happened. Catalogs carry the enrichment, and only for non-user reference data. If it describes a person, it goes in custom attributes.
- Design for next quarter, not just this sprint - Adding a property later is always more expensive than including it upfront. Ask your marketing leads what segments they'll want in six months, and design for those.
- Enforce governance before ingestion, not after - Required properties, naming conventions, schema validation: these belong in the pipeline, not in a downstream cleanup. The schema should have one owner.
- Treat iteration as normal - Even the best-planned data model evolves. The goal isn't an immutable schema; it's a structured one that's easy to extend without breaking what's already there.
Final Thought
Braze gets pitched as a messaging platform (it is a very good one at that), but it's also a very powerful segmentation engine, and that engine runs on the quality of your data model. When the data is structured well, campaigns get more precise and personalisation actually scales. When it isn't, you spend your time working around limitations instead of building, and the cost of fixing it only grows the longer you leave it.
So before your next canvas or campaign brief, the question worth asking is: is our data model enabling this, or is it holding us back?
