Skip to main content

Tags

Tags are free-form labels that can be attached to any ZeyOS entity record (contacts, accounts, transactions, tickets, etc.). Unlike ExtData, which stores structured key-value data, tags are simple strings used for categorization, filtering, and workflow routing. A single record can carry any number of tags, and the same tag name can appear on records across different entity types.

Common uses for tags include:

  • Classification — labeling contacts as "VIP", "Partner", or "Prospect"
  • Workflow state — marking records as "Needs Review" or "Approved"
  • Filtering — selecting subsets of records in queries and exports
  • Segmentation — grouping records for reports or bulk operations

Adding tags

Use tags:add to attach one or more tags to a record. Specify the entity type and record ID, then list the tag names as tags:name children:

XML
<tags:add entity="contacts" id="$contactId">
<tags:name>VIP</tags:name>
<tags:name>Newsletter</tags:name>
</tags:add>

Adding a tag that already exists on the record is a no-op — it will not create duplicates.

tags:add reference →

Tags inside db:set

When creating or updating records with db:set, you can include tags:name children directly alongside db:data and extdata:data:

XML
<db:set entity="contacts" var="contactId">
<db:data field="firstname">Ada</db:data>
<db:data field="lastname">Lovelace</db:data>
<tags:name>Customer</tags:name>
<tags:name>A-Class</tags:name>
</db:set>

This sets the record's tags as part of the same operation. Note that db:set replaces all existing tags with the ones you specify (like tags:reset), whereas tags:add appends to the existing tag set.

Removing tags

Use tags:remove to detach specific tags from a record:

XML
<tags:remove entity="contacts" id="$contactId">
<tags:name>Prospect</tags:name>
</tags:remove>

tags:remove reference →

Replacing all tags

Use tags:reset to remove all existing tags and replace them with a new set:

XML
<tags:reset entity="contacts" id="$contactId">
<tags:name>Customer</tags:name>
<tags:name>Active</tags:name>
</tags:reset>

After this call, the record has exactly two tags — regardless of what was there before.

tags:reset reference →

Reading tags

Listing tags on a record

Use tags:list to retrieve all tag names for a specific record as an array:

XML
<tags:list var="tags" entity="contacts" id="$contactId" />

<foreach var="tags" var_value="tag">
<output>$tag&n;</output>
</foreach>

tags:list reference →

Checking if tags exist

Use tags:exists to check whether a record has any tags at all:

XML
<tags:exists var="hasTags" entity="contacts" id="$contactId" />
<if value1="$hasTags">
<output>This contact has tags.</output>
</if>

To check for a specific tag, combine tags:list with an array search:

XML
<tags:list var="tags" entity="contacts" id="$contactId" />
<array:search var="tags" var_result="found">VIP</array:search>
<if value1="$found" func="!=">
<output>Contact is a VIP.</output>
</if>

tags:exists reference →

Passing tags via variable

All tag commands accept var_names to supply tag names from an array variable instead of inline tags:name children:

XML
<array var="tagList">
<item>Customer</item>
<item>Priority</item>
</array>

<tags:add entity="contacts" id="$contactId" var_names="tagList" />

Filtering queries by tags

db:intags — SQL-level tag filtering

Use db:intags inside db:select to filter results to records that carry specific tags:

XML
<db:select var_result="vips" type="assoc">
<db:fields>
<db:field>c.firstname</db:field>
<db:field>c.lastname</db:field>
<db:field>c.email</db:field>
</db:fields>
<db:table alias="c">contacts</db:table>
<db:intags entity="contacts" field="c.ID">
<tags:name>VIP</tags:name>
</db:intags>
</db:select>

You can also pass tag names from a variable:

XML
<array var="filterTags">
<item>VIP</item>
<item>Partner</item>
</array>

<db:select var_result="results" type="assoc">
<db:fields>
<db:field>c.firstname</db:field>
<db:field>c.lastname</db:field>
</db:fields>
<db:table alias="c">contacts</db:table>
<db:intags entity="contacts" field="c.ID" var="filterTags" />
</db:select>

db:intags reference →

Tag joins — db:innertags and db:lefttags

For more complex queries, you can join on the tags table directly. Use db:innertags to include only records with a specific tag, or db:lefttags to include all records while making the tag data available for conditional logic:

XML
<db:select var_result="customers" type="assoc">
<db:fields>
<db:field>c.firstname</db:field>
<db:field>c.lastname</db:field>
</db:fields>
<db:table alias="c">contacts</db:table>
<db:join>
<db:innertags alias="t" entity="contacts" name="Customer" field="c.ID" />
</db:join>
</db:select>

db:innertags reference → | db:lefttags reference →

Practical patterns

Tag-based workflow routing

XML
<tags:list var="tags" entity="tickets" id="$ticketId" />

<!-- Check if the ticket needs escalation -->
<array:search var="tags" var_result="isUrgent">Urgent</array:search>
<if value1="$isUrgent" func="!=">
<!-- Escalation logic -->
<tags:add entity="tickets" id="$ticketId">
<tags:name>Escalated</tags:name>
</tags:add>
</if>

Bulk tagging from a query

XML
<db:select var_result="overdue" type="assoc">
<db:fields>
<db:field>ID</db:field>
</db:fields>
<db:table>transactions</db:table>
<db:is field="status">0</db:is>
<db:is field="duedate" func="&lt;">$DATENOW</db:is>
</db:select>

<foreach var="overdue" var_value="row">
<tags:add entity="transactions" id="$row.ID">
<tags:name>Overdue</tags:name>
</tags:add>
</foreach>