Let the platform do the work

Tags

Overview

The tagging feature allows a user to apply as many "tags" as they choose on any record they want to categorize. This allows the user to effectively group records together from any source within the application and relate them together. Please note that the tag field and Tags module do not support customization at this time.

The Tags Module

The Tags module is a very simple module based on the Basic SugarObject template. It is not studio editable, is part of the default module list, and is available to the application upon installation. By default, the Tags module is set up such that only an Administrator can perform any administrative tasks with the Tags module. In other words, a regular user will have a very restrictive set of permissions inside the Tags module, namely: create, export, view, and share. All other actions within the Tags modules must be carried out by an Administrative user.

The "tag" Field Type

The back end utilizes two new field types: the relatecollection field and the tag field. The tag field is a relatecollection type field with a few added enhancements specific to the tagging implementation:

  1. Enforces uniqueness of a tag when created
  2. Establishes the necessary relationship between the Tags module and the module record being tagged
  3. Collects and formats a tag collection in a way the client understands
  4. Format the tag field for consumption by and from the import process
  5. Handles proper query setting for a search that is filtered by tags

The Taggable Implementation

The taggable implementation is applied to all SugarObject templates so that it is available on all custom modules created and is also applied to all sidecar enabled modules. Any module that implements a SugarObject template will be taggable by default. Any module that doesn't implement a SugarObject template can easily apply it using the uses property of the module vardefs:

  $dictionary[$module] = array(
    ...
    'uses' => array(
        'taggable',
    ),
    ...
);

There may be instances where a module should not implement tagging yet implements the SugarObject template. To remove tagging from a module you can use the module vardefs ignore_templates property:

  $dictionary[$module] = array(
    ...
    'ignore_templates' => array(
        'taggable',
    ),
    ...
);

The Tagging Relationship Structure

The tagging relationship schema is similar in nature to the email_addresses relationship schema in that it is used to represent a collection of 0-N Tags module records related to a module:

Column Description
id The GUID for the relationship between the tag record and the module record
tag_id The id of the tag record used in this relationship
bean_id The id of the module record used in this relationship
bean_module The module for the record being tagged
date_modified The date the relationship was created/modified
deleted A tinyint(1) boolean value that indicates whether this relationship is deleted

Tagging in Action

For adding tags from the UI, please refer to the Tags documentation.

Tagging Records from the API

Tagging a record via the API is done by sending a PUT request to the /<module>/<record> API endpoint with a tag property set to an array of key/value pairs that include a tag id (optional) and a tag name:

  {
    "name": "Record Name",
    "tag": [
        {"id": "Test Tag", "name": "Test Tag"},
        {"name": "Test Tag 2"},
        {"id": "1234-56-7890", "name": "Test Tag 3"}
    ]
}

After the record is created/modified and the tag values are applied, the response will contain the returned collection of tags for that record complete with their ids:

{
    "name": "Record Name",
    "tag": [
        {"id": "9876-54-3210", "name": "Test Tag"},
        {"id": "4321-56-0987", "name": "Test Tag 2"},
        {"id": "1234-56-7890", "name": "Test Tag 3"}
    ]
}

You can visit How to Manipulate Tags (CRUD) for a full example demonstrating CRUD actions for tags.

Mass Updating Tags on Records Via the API

Mass updating records with tags are as simple as sending a MassUpdate PUT request to /<module>/MassUpdate with a payload similar to:

  {
    "massupdate_params": {
        "uid": ["12345-67890", "09876-54321"],
        "tag": [
            { "id": "23456-78901", "name": "MyTag1" },
            { "id": "34567-89012", "name": "MyTag2" }
        ]
    }
}

This request will override all existing tags on the named records. To append tags to a record, send the "tag_type" request argument set to a value of 1:

  {
    "massupdate_params": {
        "uid": ["12345-67890", "09876-54321"],
        "tag": [
            { "id": "23456-78901", "name": "MyTag1" },
            { "id": "34567-89012", "name": "MyTag2" }
        ],
        "tag_type": "1"
    }
}

More information on this API endpoint can be found in the /<module>/MassUpdate PUT documentation.

Fetching Tags on a Record

By default, the tag field is added to all Sidecar module record views. That means when a request is made for a single record through the API, that single record will return the "tag" field, which will be a collection of key:value pair objects.

For example, when a request is made to the /Accounts/:record GET endpoint, the tags associated with the Accountrecord  will be returned in the tag field as an array of objects:

  {
    "id": "<record>",
    "name": "Record Name",
    "tag": [
        { "id": "9876-54-3210", "name": "Test Tag" },
        { "id": "4321-56-0987", "name": "Test Tag 2" },
        { "id": "1234-56-7890", "name": "Test Tag 3" }
    ]
}

Filtering a Record List by Tags

Filtering a list of records by tags can be done simply by sending a filter request to the ModuleApi endpoint for a module. For example, to filter the Accounts list where the tag field has a tag by the name of "Tradeshow", you can send a request to the /Accounts GET endpoint with the following request arguments:

  {
    "view": "list",
    "filter": [
        {
            "tag": {
                "$in": [
                    {
                        "name": "Tradeshow"
                    }
                ]
            }
        }
    ]
}

Currently, the tag field filter definitions support the following filter operators:

  • Is any of ($in)
  • Is not any of ($not_in)
  • Is empty ($empty)
  • Is not empty ($not_empty)

Fetching a list of Tags from the Tags module

Fetch a list of tag records from the Tags module is done the same way as fetch a list of records from any other module, namely by sending a GET request to the /Tags ModuleApi endpoint. More information can be found in the /<module> GET documentation.

Manipulating Tags Programmatically

Here is an example that demonstrates how to get all the tags and its ids related to a contact record:

  // Creating a Bean for Contacts
$bean = BeanFactory::getBean("Contacts");
// Creating a Bean for Tags
$tagBean = BeanFactory::newBean('Tags');
// Get all the tags related to Contacts Bean by givin Contact ID. You can provide more than one Record ID.
$tags = $tagBean->getRelatedModuleRecords($bean, ["<CONTACT_RECORD_ID>"]);

Creating a New Tag and Adding to a Record

Here is an example that demonstrates how to add create a tag and add to a contact record.

In order to add a new tag first, we will create the tag bean. Then using load_relationship function we will add the newly created tag id to the contacts 

  // Creating new Tag Bean
$tagBean = BeanFactory::newBean("Tags");

// Setting its name
$tagBean->name = "New Tag";
$tagBean->save();

// Retrieving the Contacts Bean
$bean = BeanFactory::getBean("Contacts", "<RECORD_ID>");

// Getting tag field and its properties
$tagField = $bean->getTagField();
$tagFieldProperties = $bean->field_defs[$tagField];

// Identifying relation link
$link = $tagFieldProperties['link'];

// Loading relationship
if ($bean->load_relationship($link)) {
    // Adding newly created Tag Bean
    $bean->$link->add($tagBean->id);
}

Removing Tags from a Record

Here is an example that demonstrates how to remove a tag from a contact record:

  // Getting the Contacts Bean
$bean = BeanFactory::getBean("Contacts", "<RECORD_ID>");

// Getting tag field and its properties
$tagField = $bean->getTagField();
$tagFieldProperties = $bean->field_defs[$tagField];

// Identifying relation link
$link = $tagFieldProperties['link'];

// Loading relationship
if($bean->load_relationship($link)){
    // Removing the Tag ID
    $bean->$link->delete($bean->id, "<TAG_RECORD_ID>");
}

Synchronizing Tags by Name With API Helpers

If you have multiple tags that you need to add and delete at the same time, then you can use SugarFieldTag->apiSave method. Here is an example that demonstrates how to sync tags by using SugarFieldTag Class for a Contact record.

It is important to know that since this is a sync; you will need to keep the existing tags if you want them to still exist in the record. 

  // Getting the Contacts Bean
$bean = BeanFactory::getBean("Contacts", "<RECORD_ID>");

// Getting Tag Field ID
$tagField = $bean->getTagField();

// Getting Tag Field Properties
$tagFieldProperties = $bean->field_defs[$tagField];

// Preparing the latest Tags to be sync with the record
$tags = [
    // Note: Already attached tags will be automatically removed from the record
    // If you want to keep some of the existing tags then you will need to keep them in the array
    "tag" => [
        // Since this tag is already added, it will be preserved
        'already added tag' => 'Already Added Tag',

        // The new tags to add - All other tags that previously existed will be deleted
        'new tag' => 'New Tag',
        'new tag2' => 'New Tag2',
    ],
];
// Building SugarFieldTag instance
$SugarFieldTag = new SugarFieldTag();

// Passing the arguments to save the Tags
$SugarFieldTag->apiSave($bean, $tags, $tagField, $tagFieldProperties);

Topics