Tags for EPiServer CMS

Posted on July 21, 2011 by Frederik Vig in EPiServer

I’ve started working on a new module for EPiServer CMS that adds tagging functionality to EPiServer Pages. This is something I’ve seen the need for in a lot of my projects lately. In the past I’ve used everything from the built in categories to custom solutions. The concept is quite simple, editors want a way to add more meta data to their pages, which then can be used for finding relevant pages, creating lists, facades navigation in search pages etc.

The module consists of two parts at the moment:

  • Custom property for adding tags to a page
  • TagEngine for finding pages with tags

Tags property

When adding Geta.Tags to your project a new custom property (Tags) will get added:

New custom property Tags

Add property Tags

In edit mode this looks something like this:

New page

Tags for EPiServer with content

Tags for EPiServer with auto complete functionality

Notice in the last screenshot that you get autocomplete for existing tags. You can add as many pages to a tag as you like, but each tag is unique, so you can only have one ‘uk’ tag, ‘europe’ tag etc.

TagEngine

TagEngine is used for finding pages based on one or more tags. You can specify a starting point (root PageReference), otherwise you’ll get back all pages tagged with that tag.

TagEngine looks like this at the moment:

public interface ITagEngine
{
    PageDataCollection GetPagesByTag(string tagName);
    PageDataCollection GetPagesByTag(Tag tag);
    PageDataCollection GetPagesByTag(string tagName, PageReference rootPageReference);
    PageDataCollection GetPagesByTag(Tag tag, PageReference rootPageReference);
    PageReferenceCollection GetPageReferencesByTags(string tagNames);
    PageReferenceCollection GetPageReferencesByTags(IEnumerable<Tag> tags);
    PageReferenceCollection GetPageReferencesByTags(string tagNames, PageReference rootPageReference);
    PageReferenceCollection GetPageReferencesByTags(IEnumerable<Tag> tags, PageReference rootPageReference);
}

I can’t promise that this is how the finale version is going to look. I’m also considering a more fluent approach.

tagEngine.Tag("customer").GetPages();
tagEngine.Tag(tag).GetPages(rootPageReference);
tagEngine.Tags(tagCollection).GetPageReferences();

I’m open to suggestions/ideas :).

Behind the scenes

All of Tags data is saved in Dynamic Data Store. When a page is saved that has a Tags property I check if it’s a new or existing tag, I then add the PageReference of the page (only PageId not WorkId) to a PageReferences collection.

[EPiServerDataStore(AutomaticallyCreateStore = true, AutomaticallyRemapStore = true)]
public class Tag
{
	public Identity Id { get; set; }
 
	public string Name { get; set; }
 
	/// <summary>
	/// Lowercase, words combined by - between them
	/// </summary>
	public string Slug { get; set; }
 
	public string Description { get; set; }
 
	// number of objects, pages that use this term
	public int Count { get; set; }
 
	public PageReferenceCollection PageReferences { get; set; }
}

There are a couple of problems with this approach:

  • Mirroring – not guaranteed to get the same PageId
  • Globalization – same tags get added to all versions

I then have a scheduled job that basically cleans everything up, makes sure there are no PageReferences to pages that no longer exist or have removed their tag. This job is not implemented yet.

Coming soon

  • A more stable version for nuget.episerver.com
  • Implementation of TagEngine and TagsScheduledJob
  • Settings class for the Tags property

Project homepage

You can find the project homepage on EPiCode and the source code here.

I’m very open to suggestions and ideas. Do you think this will be useful?

Related Posts: