A viz extension has no field picker, no dashboard, and no way to choose data for itself. Every value it draws is there because the user dragged a field onto a tile on the worksheet's Marks card, and those tiles exist only because you declared them as encodings in the manifest. Declare none and the extension loads with nowhere to drop anything and silently renders empty, which is the single most common way a viz extension fails.
#What a Marks-card tile is
Each <encoding> block in a <worksheet-extension> manifest becomes one tile on the Marks card. The user drops a field on it, and at runtime you read which field landed on which tile. A tile is defined by its id (the key your code reads), a display name, what it accepts, how many fields it takes, and the icon Tableau draws beside it.
<encoding id="value">
<display-name>Value</display-name>
<data-spec><data-type>numeric</data-type></data-spec>
<role-spec><role-type>continuous-measure</role-type></role-spec>
<fields max-count="1"/>
<encoding-icon token="metric"/>
<tooltip>The measure the bar shows (e.g. Sales).</tooltip>
</encoding>
The children run in a fixed order: display-name, data-spec, role-spec, fields, encoding-icon, tooltip.
#The four-encoding cap
Tableau accepts at most four custom encodings per viz extension (the schema sets maxOccurs=4). A fifth makes the whole .trex fail to load. In practice two to four tiles is right: mark the ones the chart truly needs as required and leave enrichment (color, size, a label) optional.
#What a tile accepts
Two specs restrict a tile. <data-spec><data-type> is one of numeric, temporal, string, boolean. <role-spec><role-type> is one of continuous-measure, discrete-dimension, continuous-dimension, discrete-measure. Tableau enforces both, so a numeric + continuous-measure tile refuses a text field. The common shorthands:
| Accepts | data-type | role-type |
|---|---|---|
| dimension | (any) | discrete-dimension |
| measure | numeric |
continuous-measure |
| date | temporal |
(any) |
| any | (none) | (none) |
<fields max-count="N"/> caps how many fields land on one tile. Almost always 1; use a higher number, or omit for unlimited, only when combining several dimensions into one key is genuinely meaningful (the kit's bullet chart lets Category take up to three).
#Detail and tooltip are reserved
Never name a custom tile detail or tooltip. Those are the ids Tableau's own built-in Marks-card tiles report from getVisualSpecificationAsync(), so a custom tile sharing one is indistinguishable from the built-in at runtime and the reader cannot tell them apart. Use a specific id (city, note, from, to). The built-in Detail and Tooltip tiles are always present automatically; you do not declare them.
#Every icon must be different
<encoding-icon token="…"> sets the glyph on the tile, and the token must come from Tableau's fixed enumeration compiled into the product. Two consequences bite:
- The published docs list tokens the parser rejects, such as
lineanddetail. An unlisted token makes Tableau reject the whole manifest at add time. See the authoritative token list. - Every tile's icon must differ from every other tile's. Two tiles sharing a token (two measures both
metric, two dimensions bothlevel-of-detail) fail on add with errorED626076, "Cannot use the same icon for more than one encoding", and a workbook that embedded the manifest then fails to open.
Conventions worth reusing: a primary measure metric, a target forecast, a from/to pair arrow-left and arrow-right, a category level-of-detail, an x/y pair letter-x and letter-y.
#How the // fields: line maps to tiles
When you build a hosted viz extension, you do not hand-write the <encoding> XML. Your component carries a // fields: metadata comment, and the host reads it and writes one <encoding> per entry into the .trex:
// fields: [{"id":"item","name":"Item","accepts":"dimension","max":1,"required":true,"icon":"level-of-detail","hint":"One mark per value."},{"id":"value","name":"Value","accepts":"measure","max":1,"required":true,"icon":"metric","hint":"Bar length, e.g. SUM(Sales)."}]
Each entry's id is the key your code reads from the fields prop, accepts becomes the data and role specs, max becomes max-count, icon becomes the token, and hint becomes the tooltip. required has no home in a .trex (Tableau has no notion of a mandatory encoding), so it drives the extension's own splash screen instead. The host normalises the list: it drops any invalid icon token and caps the array at four. See the component contract for where this line lives.
#FAQ
#How many encodings can a viz extension declare?
Four, at most. The schema caps <encoding> at maxOccurs=4 and a fifth makes the .trex fail to load. Two to four is the practical range: required tiles for what the chart needs, optional ones for enrichment.
#Why can I not name a tile "detail"?
detail and tooltip are the ids Tableau's built-in Marks-card tiles report at runtime. A custom tile with one of those ids is indistinguishable from the built-in when you read the visual specification, so the reader cannot resolve your field. Use a specific id instead.
#What is error ED626076?
Two encodings share an encoding-icon token. Tableau refuses the manifest on add ("Cannot use the same icon for more than one encoding") and any workbook that already embedded it fails to open. Give every tile a distinct, valid token.
#Where do I put required and the tooltip text?
required is not a .trex concept, so in the hosted builder it lives on the // fields: line and drives a splash screen until the required tiles are bound. The tooltip text becomes the encoding's <tooltip> element on the tile.