What are Custom Fields?

Custom Fields let you keep one shared dataset for all your customers, while giving each customer the extra fields that only they need.

Many software companies that embed Luzmo start with one copy of a dataset per customer. It works, until you need to rename a field, fix a formula, or change a format: the change has to be repeated on every copy, and over time the copies drift apart.

With Custom Fields, you manage a single dataset. Fields that everyone uses stay shared. Fields that only one customer (or a few customers) need are scoped to those tenants, so only they see them. Fix a shared calculation once, and every customer gets the fix.

A Custom Field can be:

  • an existing source column of your dataset
  • a derived column
  • an aggregation formula
  • an extra column that exists only in a tenant's own data source (see Tenant data sources)

Key concepts

Tenants

A tenant represents one of your end customers. You create tenants through the API, and you link an embed token to a tenant when your customer's users open a dashboard or the embedded dashboard editor.

If you already use suborganizations in your embed tokens, the tenant defaults to the suborganization value, so every customer is mapped to a tenant in the same way.

Shared fields and tenant fields

Every field in a dataset is either shared or scoped to one or more tenants.

Field scope Who sees it How it gets this scope
Shared All tenants, and your organization Default. Every field without a tenant assignment is shared.
Tenant field Only the assigned tenants, and your organization You assign the field to one or more tenants, or a tenant creates it in the embedded dashboard editor.

A few rules to keep in mind:

  • A field without any tenant assignment is shared. Your existing datasets keep working exactly as before.
  • The first assignment limits a field to the assigned tenants. Assignments add up: a field can be visible to tenant A and C, but not B.
  • Removing the last assignment makes the field shared again.
  • Users of your own organization always see every field.

A worked example

Imagine an Opportunities dataset that you share with three customers.

Field Type Scope
Opportunity ID Source column Shared
Amount Source column Shared
Status Source column Shared
Win rate Formula Shared
Sales Region Source column Acme
Contract Value Derived column Acme
Renewal Risk Source column Globex
Implementation Phase Source column Initech

When an Acme user opens the dashboard editor, the field list shows the four shared fields plus Sales Region and Contract Value. A Globex user sees the shared fields plus Renewal Risk. Nobody sees the fields of another customer, and none of them can tell those fields exist.

If you improve the Win rate formula, all three customers get the new version immediately.

When should you use Custom Fields?

Custom Fields are a good fit when:

  • your customers share a core data model, but each needs a few fields of their own
  • you maintain many copies of the same dataset and want to reduce them to one
  • your customers build their own derived columns or formulas in the embedded dashboard editor, and those should stay private to them

Custom Fields are less suited when:

  • all customers use exactly the same fields: a regular shared dataset is enough
  • customers have completely different data models: separate datasets remain simpler
  • customer-specific attributes are stored as JSON inside a single column
You want to… Use
Add a row-level calculation for everyone A shared derived column
Add a metric for everyone A shared aggregation formula
Show a column, derived column or formula to specific customers only Assign it to those tenants
Let a customer create private fields Give them the embedded dashboard editor with a tenant-scoped token
Give a customer extra columns from their own database A tenant data source

How to set up Custom Fields

Setup is done through the Luzmo API today. Your end users don't need to do anything: tenant fields simply appear in the field list of the dashboard editor and the embedded dashboard editor.

1. Create a tenant

Create one tenant per end customer, with a unique identifier and a display name.

POST https://api.luzmo.com/0.1.0/tenant
{
  "action": "create",
  "version": "0.1.0",
  "key": "<your API key>",
  "token": "<your API token>",
  "properties": {
    "identifier": "acme",
    "name": { "en": "Acme Corp" }
  }
}

2. Link your embed tokens to the tenant

When you create an embed authorization for a customer's user, pass the tenant property. If you also pass suborganization, both values must be equal.

"properties": {
  "type": "embed",
  "username": "user-123",
  "suborganization": "acme",
  "tenant": "acme",
  ...
}

3. Assign fields to tenants

Associate a column (source or derived) or a formula with a tenant:

POST https://api.luzmo.com/0.1.0/column
{
  "action": "associate",
  "version": "0.1.0",
  "key": "<your API key>",
  "token": "<your API token>",
  "id": "<column id>",
  "resource": { "role": "Tenants", "id": "<tenant id>" }
}

Use /0.1.0/formula to assign a formula, and dissociate to remove an assignment.

To assign many fields in one call, use the bulk action on the tenant resource. A bulk call is all-or-nothing: if one assignment fails, none are applied.

POST https://api.luzmo.com/0.1.0/tenant
{
  "action": "associate",
  "version": "0.1.0",
  "key": "<your API key>",
  "token": "<your API token>",
  "assignments": [
    { "tenant_id": "<acme id>", "resource": { "role": "Columns", "id": "<sales region id>" } },
    { "tenant_id": "<acme id>", "resource": { "role": "Formulas", "id": "<contract value id>" } }
  ]
}

4. Add the fields to your dashboards

Tenant fields are not added to dashboards automatically. Build dashboards with shared fields to serve every tenant with one dashboard. When a dashboard uses tenant fields, create it for (or let it be created by) the tenants that can see those fields.

Fields created by your customers

When a customer's user creates a derived column or a formula in the embedded dashboard editor with a tenant-scoped embed token, the new field is automatically scoped to that tenant. Other customers never see it, and you don't need an extra API call.

Fields created by users of your own organization stay shared, unless you assign them.

A tenant can only build on fields it can see. If a derived column or formula references a field that is hidden for the tenant, creation fails with the same error as for a field that doesn't exist. This keeps other customers' fields private.

Tenant data sources

Some customers store their data in their own database, with a few extra columns on top of your standard model. With a tenant data source, one logical dataset reads each tenant's data from that tenant's own connection and table (or SQL query).

  • Columns that match the shared fields of the dataset are used as shared fields.
  • Extra columns in the tenant's source are discovered automatically and appear as tenant fields for that tenant only.
  • If two tenants each have a column with the same name, for example Sales Region, each tenant gets its own separate field.
  • When a column is added to or removed from the tenant's source, the field list follows automatically.

You create a tenant data source through the API with the tenantdatasetsource resource, which links a tenant and a dataset to a connection plus either a table or a SQL query.

Limitations

  • API-only setup. There is no Luzmo editor screen to manage tenant assignments yet.
  • No automatic filters. Tenant scoping controls which fields are visible, not which rows. Keep using your usual row-level security, such as embed token filters or parameters, to limit data.
  • No automatic migration. Existing per-customer dataset copies are not merged into a shared dataset automatically.
  • No "edit as customer" preview. In the Luzmo editor, your organization sees every field. You can't preview the field list of a specific tenant there.
  • Charts using a hidden field. If a dashboard contains a chart that uses a field the viewer can't access, that chart shows "Query failed". The rest of the dashboard still loads.
  • Tenant data sources:
    • Warp acceleration is not supported.
    • JSON attributes are not supported.
    • Renaming a column in the tenant's source doesn't rename the field. The old field becomes unavailable, a new field appears, and charts or formulas that used the old field need updating.

Best practices checklist

  • Start by moving the fields that every customer uses into one shared dataset.
  • Only scope a field when it really belongs to specific customers. Shared is the default for a reason.
  • Use a consistent tenant identifier, ideally the same value you already use as suborganization.
  • Build your standard dashboards on shared fields only, so one dashboard serves every tenant.
  • Use bulk assignments when you onboard a customer with many fields.
  • Keep tenant data sources aligned with your shared model: same provider, same shared column names and types.
  • Avoid renaming columns in tenant sources, or plan to update the charts that use them.

FAQ

Do I need to enable Custom Fields?

No. Custom Fields are available without a feature flag. Fields without a tenant assignment remain shared, so existing datasets are unaffected.

Are Custom Fields a security feature?

They control which fields a tenant can see and query: a hidden field is removed from the field list and can't be queried. They don't restrict rows. Use embed token filters, parameters or separate connections for row-level access.

Can a field be visible to several tenants?

Yes. Assign the same column or formula to each tenant that needs it.

Can my customers create their own fields?

Yes. Derived columns and formulas created in the embedded dashboard editor with a tenant-scoped token are automatically scoped to that tenant.

What happens when I delete a tenant?

The fields that tenant created are cleaned up together with the tenant.

What's the difference with suborganizations?

A suborganization groups the users of one customer for things like access and ownership. A tenant defines which dataset fields that customer sees. In most setups they use the same value.

Related articles

Need more information?

Do you still have questions? Let us know how we can help.
Send us feedback!