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:
In this article
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.
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:
Imagine an Opportunities dataset that you share with three customers.
| Field | Type | Scope |
|---|---|---|
| Reference | Source column | Shared |
| Amount | Source column | Shared |
| Status | Source column | Shared |
| Win rate | Formula | Shared |
| Customer tier | Tenant data source column | Customer A |
| Contract value | Derived column | Customer A |
| Region | Tenant data source column | Customer B |
| Lead source | Tenant data source column | Customer B |
When a user of Customer A opens the embedded dashboard editor, the field list shows the shared fields plus Customer A's own fields, such as Customer tier. A user of Customer B sees the shared fields plus Region and Lead source. Customer C only sees the shared fields. 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.
Custom Fields are a good fit when:
Custom Fields are less suited when:
Which kind of Custom Field to use depends on where the data lives:
| Your situation | Use |
|---|---|
| A calculation only some customers need | A derived column or formula, assigned to those tenants |
| Each customer's data lives in its own table, database or SQL view, with extra columns on top of a common model | Tenant data sources |
| One shared table that already contains a few columns only relevant to one customer | Assign those existing columns to that tenant |
| Customers create their own fields | The embedded dashboard editor with a tenant-scoped token |
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.
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": "customer-a",
"name": { "en": "Customer A" }
}
}
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. The token must still give access to the dataset: see Access and permissions.
"properties": {
"type": "embed",
"username": "user-123",
"suborganization": "customer-a",
"tenant": "customer-a",
"access": { "datasets": [{ "id": "<dataset id>", "rights": "use" }] },
...
}
You assign a field to a tenant by associating it with that tenant. The field itself doesn't change: it simply becomes visible to the assigned tenants only.
A derived column or formula. Create it as usual on the dataset (in the dataset editor, or through the API), then associate it with the tenant.
An existing source column. The column is already in your dataset after the metadata sync. Associate it directly: there is no need to delete or recreate it.
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. With the SDKs, this is the regular associate call, for example client.associate('column', columnId, { role: 'Tenants', id: tenantId }).
Assigning many fields at once. For onboarding, you can send several assignments in a single HTTP request on the tenant resource. The request is all-or-nothing: if one assignment fails, none are applied. This request shape isn't available as an SDK method: send it as a plain HTTP request.
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": "<tenant A id>", "resource": { "role": "Columns", "id": "<column id>" } },
{ "tenant_id": "<tenant A id>", "resource": { "role": "Formulas", "id": "<formula id>" } }
]
}
Tenant fields are not added to dashboards automatically.
Tenant scoping is an extra filter on top of the access you give in the embed token. It never grants access on its own: a tenant user only sees the tenant fields of datasets their token gives access to.
| Action by a tenant user | use on the dataset |
modify on the dataset |
|---|---|---|
| Create a derived column or formula (scoped to their tenant automatically) | Yes | Yes |
| Rename, reformat, change or delete their own derived columns and formulas | Yes | Yes |
| Change a derived column or formula assigned to several tenants | No | Yes |
| Change a shared derived column or formula | No | No |
| Rename, reformat or edit the hierarchy of a source column, including a shared one | No | Yes |
| Manage tenant assignments | No | No |
Creating tenants, assigning fields and managing tenant data sources is reserved to users of your main organization:
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.
Some customers store their data in their own database or schema, 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 table, or from a SQL query.
Create a tenant data source with the tenantdatasetsource resource. It links a tenant and a dataset to a connection, plus exactly one of source_sheet (a table) or source_query (a SQL query).
POST https://api.luzmo.com/0.1.0/tenantdatasetsource
{
"action": "create",
"version": "0.1.0",
"key": "<your API key>",
"token": "<your API token>",
"properties": {
"tenant_id": "<tenant id>",
"securable_id": "<dataset id>",
"account_id": "<connection id>",
"source_query": "SELECT reference, customer, amount, status, created_date, region, lead_source FROM customer_b.opportunities"
}
}
identifier, ideally the same value you already use as suborganization.use rights on shared datasets.No. Custom Fields are available without a feature flag. Fields without a tenant assignment remain shared, so existing datasets are unaffected.
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.
Yes. Assign the same column or formula to each tenant that needs it.
Yes. Derived columns and formulas created in the embedded dashboard editor with a tenant-scoped token are automatically scoped to that tenant, and they can manage them with use rights.
Not on its own: a filter or chart always points to one specific field, and a tenant's field doesn't exist for other tenants. Keep one template on shared fields, and create a variant per customer that has custom fields.
The fields that tenant created are cleaned up together with the tenant.
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.