Your Order Data Is in HubSpot - Your Layout Just Won't Show It
Here's a scenario we ran into recently with a client syncing their ERP into HubSpot: every sales order flows into the Orders object, and the line items come with it - with full details for each item across a number of custom properties. The data is in HubSpot. But open an order record and the line items card shows exactly three things: SKU, quantity, and total price.
If your team has ever pulled up an order in HubSpot and then had to open the ERP anyway to see what was actually on it, this one's for you.
What's Actually Happening
The line items card on the Orders object is one of HubSpot's locked association cards - the columns are fixed, and there's no setting to change them. We confirmed it with HubSpot support: there previously was a way to build a custom association card for exactly this, but it sounds like the feature had issues and was removed. So the data sits complete on the record while the layout shows a fraction of it.
The good news is that the replacement path is better than what was removed - and more available than most people think. Custom cards now live in HubSpot's app card framework (UI extensions): small React components that render right on the record page, powered by a private app you build for your own portal. And since November 2024, private app cards work on any Enterprise-tier hub - not just Sales or Service Hub Enterprise.
Why Not Just Work Around It?
We talked through the alternatives before building, and they're worth knowing:
A formatted text property filled by workflow custom code, but properties render plain text only - no real table - and there's a trap in the trigger design: line items aren't a workflow enrollment object, and integrations typically create the order before attaching its lines, so event-based triggers fire too early. You end up needing a nightly sweep, which means the field is always slightly stale.
A custom object copy of the line data gets you a configurable native card, but now the same data lives in two places and your integration vendor has to maintain a second mapping.
An app card avoids both problems: it fetches the associated line items live every time the record loads. Nothing is duplicated, nothing can drift out of sync, and it's read-only by nature.
The Build
The card itself is a single React component. HubSpot's useAssociations hook pulls the associated line items with whatever properties you want - native and custom - and the table renders from a simple column config:
const { results, error, isLoading } = useAssociations({
toObjectType: "0-8",
properties: COLUMNS.map((c) => c.key),
pageLength: 100,
});
We drove the whole table from a COLUMNS array of {key, label, format} entries, which makes it very simple to modify the specific properties that are displayed.
Findings Worth Sharing
The build was quick. The potholes were not obvious. Here's what we learned so you don't have to:
Deploying is not installing. hs project upload builds and deploys your app, but the card appears nowhere until you also open the project in HubSpot, click into the app, and install it from the Distribution tab. There's no error telling you this - the card is just absent.
Look in the Card Library. Once installed, the card shows up in record customization under the Card Library, not under the Apps section.
Use type IDs, not object names. useAssociations rejects friendly names like line_items - it wants the object type ID (0-8 for line items, 0-123 for orders).
Empty properties vanish from the response. If a property has no value, the hook omits it entirely rather than returning it blank. A column that's empty on every row is ambiguous: wrong internal name, or genuinely empty data. Check against a record you know has the value before debugging the wrong thing.
The footer stays. Every app card carries a "Powered by [your app name]" footer with a Settings link. It's HubSpot's chrome and can't be removed - but the app name is yours to choose, so name it something presentable.
The removal of custom association cards left a real gap, and the locked line items card is where teams feel it most. But the app card framework ultimately became the better answer - live data, real tables, and full control over columns. If the data is already on your records, your layout shouldn't be the reason nobody can see it.
Running into the same wall with orders, line items, any locked card in your portal, or just want to improve the visibility of your data beyond the standard views? We'd be more than happy to help.

