﻿#### Sitecore Cortex: Extend Content Tagging 

If you have experience with Sitecore **Content Tagging** feature, you should know that content tagging applies only to itseft item`s content.

How Content Tagging retrieve items content:

1. Get all item fields that have *"Multi-Line Text"* or *"Rich Text"* type.
2. Filter standart fields *(to prevent exctracting theirs content)*.
3. Exctracts text contect from these result fields and combines them.

Very often you have items in Sitecore has no much content in their own fields, but consist of many renderings with datasources, like following:

![Items presentation](https://www.brimit.com/-/media/project/brimit/blog/2020/x3mxray/content-tagging-layout.jpg)

And if you want to tag item like this including all rendering datasorces *(that have significant to item contect)*, then you will not succeed. Let`s implement our own extention to achieve our goals.

First of all we need to implement some item extentions that we will use to retrieve item renderings and their datasources:

```
      
using System;
using System.Collections.Generic;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Layouts;

namespace Foundation.ContentTagging.Extentions
{
    public static  class ItemExtentions
    {
        public static List<Item> GetDataSourceItems(this Item i)
        {
            List<Item> list = new List<Item>();
            foreach (var reference in i.GetRenderingReferences())
            {
                Item dataSourceItem = reference.GetDataSourceItem();
                if (dataSourceItem != null)
                {
                    list.Add(dataSourceItem);
                }
            }
            return list;
        }

        public static Item GetDataSourceItem(this RenderingReference reference)
        {
            return reference != null ? GetDataSourceItem(reference.Settings.DataSource, reference.Database) : null;
        }

        private static Item GetDataSourceItem(string id, Database db)
        {
            return Guid.TryParse(id, out var itemId)
                ? db.GetItem(new ID(itemId))
                : db.GetItem(id);
        }

        public static RenderingReference[] GetRenderingReferences(this Item i)
        {
            if (i == null)
            {
                return new RenderingReference[0];
            }
            // default sitecore Device
            var defaultDeviceItem = i.Database.Resources.Devices[new ID("{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}")];
            return i.Visualization.GetRenderings(defaultDeviceItem, false);
        }
    }
}

```

Next we need to implement our custom processor for **tagContent** pipeline that will retrieve text content from our rendering datasources and add it to result tagging content list:

```
      
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation.ContentTagging.Extentions;
using Sitecore.Data.Items;
using Sitecore.ContentTagging.Core.Models;
using Sitecore.ContentTagging.Core.Providers;
using Sitecore.ContentTagging.Pipelines.TagContent;

namespace Foundation.ContentTagging.Pipelines.TagContent
{
    public class RetrieveContentFromDatasourceItems
    {
        public void Process(TagContentArgs args)
        {
            var taggableContentList = new List<TaggableContent>();
            if (args.Content != null && args.Content.Any())
            {
                taggableContentList.AddRange(args.Content);
            }

            foreach (IContentProvider<Item> contentProvider in args.Configuration.ContentProviders)
            {
                var dataSoutceItems = args.ContentItem.GetDataSourceItems();
                foreach (var item in dataSoutceItems)
                {
                    var content = (StringContent)contentProvider.GetContent(item);

                    if (!string.IsNullOrEmpty(content.Content) && !string.IsNullOrEmpty(content.Content.Trim()))
                    {
                        taggableContentList.Add(content);
                    }
                }

            }
            args.Content = taggableContentList;
        }
    }
}

```

And latest, we need to patch **tagContent** pipeline to add our custom processor right after default *Sitecore.ContentTagging.Pipelines.TagContent.RetrieveContent*:

```
      
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
    <sitecore role:require="Standalone or ContentManagement">

        <pipelines>
            <group name="ContentTagging" groupName="ContentTagging">
                <pipelines>
                    <tagContent>
                        <!-- Extract text content from all datasource items that are used in item presentations, remove it if you don`t need -->
                        <processor type="Foundation.ContentTagging.Pipelines.TagContent.RetrieveContentFromDatasourceItems, Foundation.ContentTagging"
                                   patch:after="processor[@type='Sitecore.ContentTagging.Pipelines.TagContent.RetrieveContent, Sitecore.ContentTagging']"
                                   resolve="true" />
                    </tagContent>
                </pipelines>
            </group>
        </pipelines>
    </sitecore>
</configuration>
```

Let`s test it!

- Create an item with text that we will use as a datasource: ![](https://www.brimit.com/-/media/project/brimit/blog/2020/x3mxray/content-tagging-test.jpg)
- Create testing item without any text data and set datasource item in any rendering in presentation details: ![](https://www.brimit.com/-/media/project/brimit/blog/2020/x3mxray/content-tagging-test-2.png)
- Run "Tag item" command from ribbon menu and see result : ![](https://www.brimit.com/-/media/project/brimit/blog/2020/x3mxray/content-tagging-result.png)

Finally, if you need more field types that will used for content tagging, for example if you want to include *"Single-Line Text"* fields to processing, you can patch **contentTagging** section like following:

```
      
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
  <sitecore role:require="Standalone or ContentManagement">
    <contentTagging>
    <fieldMap>
        <fieldTypes>
            <fieldType fieldTypeName="Single-Line Text"/>
        </fieldTypes>
    </fieldMap>
</contentTagging>
</sitecore>
</configuration>
```

**UPDATE:** Source code is available on [GitHub](https://github.com/x3mxray/ContentTagging.Extentions).

###### Author

[!\[sergey-200\](https://www.brimit.com/-/jssmedia/feature/blogs/authors/sergey-200.jpg?h=197&amp;iar=0&amp;w=200&amp;hash=0D636570F87F1C13C39E06EB19D9DF06)
Sergey Baranov
Sitecore MVP/ Senior Sitecore Developer](https://www.brimit.com/blog/author?authors=Sergey%20Baranov)

#### More on Sitecore

[!\[How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2024/vercel_cover-image.png)
#Guides#How-toDXPE-commerce
##### How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects
Optimize and accelerate the development and deployment of complex multisite Sitecore projects.
Alexei Vershalovich on July 17, 2024](https://www.brimit.com/blog/how-vercel-will-help-you-save-effort-when-deploying-sophisticated-sitecore-projects)

[!\[Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2023/sitecore-mentoring---cover-image.png)
#How-toDXP
##### Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story
How to participate in the Sitecore Mentor program and help younger colleagues jump-start a career in Sitecore development.
Sergey Baranov on October 2, 2023](https://www.brimit.com/blog/training-up-tomorrows-sitecore-mvps)

[!\[Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2022/headless/adobestock_456986731.jpg)
#How-toDXPE-commerce
##### Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)
Discover how a headless CMS can benefit organizations that use Sitecore.
Daniil Raschupkin, Palina Trokhautsava on September 15, 2022](https://www.brimit.com/blog/going-headless-part-2-when-a-headless-cms-is-your-best-bet-if-you-have-sitecore)

![](https://bat.bing.net/action/0?ti=187017043&amp;tm=gtm002&amp;Ver=2&amp;mid=5b2a53b1-22cb-4d33-a116-b2129937355b&amp;bo=2&amp;gtm_tag_source=1&amp;pi=0&amp;lg=en-US&amp;sw=800&amp;sh=600&amp;sc=24&amp;nwd=1&amp;tl=Sitecore%20Cortex%20Content%20Tagging%3A%20Extract%20rendering%20datasource%60s%20content&amp;kw=sitecore,%20cortex,%20content,%20tagging,%20extention,%20datasource&amp;p=https%3A%2F%2Fwww.brimit.com%2Fblog%2Fcortex-content-tagging-extentions-datasources&amp;r=&amp;lt=336&amp;evt=pageLoad&amp;sv=2&amp;asc=D&amp;cdb=AQAY&amp;rn=945973)