Understanding placement-scoped custom attributes

Last updated: July 30, 2026

When a form references a custom attribute scoped to the placement, every task created from that form needs a value for it. If the value won't exist on every placement, collect it as a field on the form instead.

What it is

Custom attributes are the fields your account defines on top of Onboarded's built-in data. Each one is scoped to an entity — employee, employer, client, job, placement, or form — and that scope decides where the value lives and how often it changes. Placement-scoped attributes are the ones that change with every hire: pay rate, start date, employment type, work location.

The moment a form references a placement-scoped attribute — in a field path, a rule, a content block, or a PDF mapping — that form becomes scoped to the attribute. Onboarded then treats the value as a hard requirement for every task built from that form.

If you remember nothing else: referencing placement.custom_attributes.{field} anywhere in a form makes that attribute mandatory for every task

Why it matters

This is the mechanic behind two symptoms that look unrelated but share one cause. Either the form never appears as a requirement on a placement, or creating the task fails outright with an error saying the scoped custom attribute value wasn't found. In both cases the attribute is referenced by the form and has no value on that placement.

It matters most when:

  • The value only applies to a subset of your hires — an allowance that exists for exempt roles and not hourly ones.

  • The value comes from an upstream ATS or HRIS that only populates it under certain conditions.

  • The value is calculated by a person rather than stored anywhere — a figure someone works out at offer time.

How it works

Onboarded tracks where the attribute is referenced

When you publish a form version, Onboarded scans it for custom attribute paths — field paths, rule conditions, review-table options, translated content, and PDF field mappings all count. Every path it finds gets recorded against the form. If a referenced attribute doesn't exist in the account at all, publishing fails and tells you which ones are missing.

Forms without a value are filtered out

When a placement is created or updated, Onboarded evaluates which forms apply to it. A form scoped to a placement attribute is only considered if the placement has a value for that attribute. No value means the form is skipped — it never becomes a suggested task, so nothing appears to explain the absence. This is why a policy can look correctly configured and still produce no task.

Task creation is the enforcement point

Creating a task from a placement-scoped form without a placement fails, as does creating one where the scoped attribute has no value. Both return an error naming the attribute, which makes them easy to diagnose once you know to look for them.

The value is captured once, at task creation. Onboarded copies the attribute's value onto the task when the task is made. Changing the value on the placement afterward doesn't reach a task that already exists — the generated document keeps the value it was built with. If a figure needs to be corrected after the fact, the task has to be recreated.

The alternative: ask for it on the form

When a value won't reliably exist on every placement, put it on the form as a field on an employer-assigned page instead of as a custom attribute. The employer enters it when they work the task, and the PDF mapping merges it into the generated document exactly the way it would merge a custom attribute. The trade is that someone types it every time — but the form works for every placement, and nothing depends on an upstream system populating a field it doesn't always have.

Example

Take an account that hires highly compensated employees on an hourly rate but has to issue an offer letter stating a minimum annualized amount. The amount isn't stored anywhere — someone calculates it from the hourly rate and the guaranteed weekly hours.

The instinct is to add placement.custom_attributes.annualized_amount and send it in with the placement. That works for the handful of placements where the figure exists. Every other placement then either can't use the form or fails to produce the task, because the attribute is now required for all of them.

Adding a currency field to the employer page of the offer letter form instead keeps the form usable across the board. The person making the placement enters the annualized amount alongside the recruiter name they're already filling in, the field is required so it can't be skipped, and the PDF mapping drops it into the offer letter. No upstream change, no attribute that has to be present on every placement.

Read next