Jeremy Davis
Jeremy Davis
Sitecore, C# and web development
Article printed from: https://blog.jermdavis.dev/posts/2023/sitecore-rss-utm

Adding UTM codes to RSS links in Sitecore

An nice little example of extending Sitecore's default RSS Feed implementation

Published 25 September 2023
Sitecore RSS ~4 min. read

There aren't that many places where RSS gets used these days (Shame! It's still good!), but that doesn't stop the occasional requirement for it coming up in projects. Recently I was having some discussions about how a client's site could offer RSS for their content which included custom UTM codes in the feed links. That's not too tricky to achieve with Sitecore, so here's an example of what you might do.

Basic config url copied!

Out of the box, Sitecore lets you create RSS feeds for your content fairly easily. There is documentation for this, but to summarise: You can create an item based on the /sitecore/templates/System/Feeds/RSS Feed data template to put a feed into your content tree. That item's location and name sets the URL for the feed you're creating. The item lets you set metadata for lots of feed properties like titles and copyrights etc. But it also gives you a field to specify what content to list in the feed. You either pick a folder (to put its descendants into the feed) or you specifying a data query to pick out a set of items to use.

Creating a feed in the content tree, and specifying a folder of source items

But to make the feed work, you also have to teach Sitecore how to render the data template(s) that might appear in your feed. You can select an item of each of the types your feed needs to show, and click the "Design" button on the "Presentation" ribbon. That gives you a dialog which allows you to map the key fields you need in your feed:

Clicking the 'Design' button to open the RSS item mapping dialog

Under the surface this is a shortcut for configuring an RSS Device in the presentation details, which configures a FeedRenderer rendering and lets you specify mappings from your source fields to the result. The Rendering Parameters for this have some pre-defined common fields RSS fields you can map, plus it allows further fields to be mapped by the Additional Parameters dictionary:

Sitecore Content Editor showing the Layout Details for an RSS feed item, and the Rendering Parameters which map the item's data to RSS fields

Once you set this up and publish changes your feed is ready to go - but there is another issue you need to consider. The way these feeds are implemented in code requires you to be an authenticated user to fetch the data. But since most uses of feeds need them to be accessible to anonymous users (like feed readers) you'll need to follow the instructions in this support article, to update your web.config and enable anonymous access.

And once you've done all that you can browse a feed:

The XML of an example RSS feed generated by Sitecore

For many situations that's all that needs doing. But it won't handle the custom UTM codes I was interested in...

Adding custom stuff url copied!

The scenario I was looking at needed to add a UTM query string based on fields from the item and from some constants. While it's not covered in Sitecore's official docs, the RSS Feed Item created above has a field to specify a custom class for processing your feed. Here you can specify a type of your own which inherits from Sitecore.Syndication.PublicFeed and this will get called for each item your feed is rendering. You specify this as a .Net type name in the usual "type-name, dll-name" format:

The Sitecore Content Editor showing the field for specifying a custom processing type in an RSS Feed definition

To match that definition, the class definition looks like:

using Sitecore.Syndication;

namespace Blog.RSS
{
    public class CustomFeed : PublicFeed
    {
    }
}

					

In that class you override the RenderItem() method and put in your own logic. You can use this to generate the feed item entirely yourself (ignore the base method entirely), or you can call the base method and them modify the resulting item. The data this method generates is an object based on Microsoft's SyndicationItem type, which includes fields for all the common data you need for a feed item.

For my scenario where I wanted to extend the URL with a UTM code, the simplest approach to the custom code is to call the base, grab the link it generates and then update that to include the extra querystring fields. Something like:

protected override SyndicationItem RenderItem(Item item)
{
    var result = base.RenderItem(item);

    var link = result.Links[0];

    var queryToAppend = GenerateUtmFields(item, "mySite","rss");
    var newUri = new UriBuilder(link.Uri);
    newUri.AppendQuery(queryToAppend);

    result.Links[0].Uri = newUri.Uri;

    return result;
}

					

Real-world code would probably want to iterate the Links collection rather than just processing the first one. (Or actually test that there is a link at all for safety...) But this is good enough for a quick demo.

The GenerateUtmFields() method can take whatever data is relevant to the logic required, and produce a set of querystring fields to match. As a very simple example, that might be:

private string GenerateUtmFields(Item item, string source, string medium)
{
    var term = item.Fields[UtmTermFieldId].Value;

    return $"utm_source={source}&utm_medium={medium}&utm_term={term}";
}

					

The UtmTermFieldId value would be a constant ID for the relevant Sitecore field on your data item.

If your feeds would be processing multiple data templates you'd need something more complex here to look at what type of item was currently being processed and make sure you access the relevant fields. But overall, you'd make use of whatever your own business logic was here.

And the call to AppendQuery() above is an extension method to ensure that adding the querystring is applied correctly:

public static class UriBuilderExtensions
{
    public static void AppendQuery(this UriBuilder builder, string queryToAppend)
    {
        if (builder.Query != null && builder.Query.Length > 1)
        {
            builder.Query = builder.Query.Substring(1) + "&" + queryToAppend;
        }
        else
        {
            builder.Query = queryToAppend;
        }
    }
}

					

If the URI already has a querystring you need to append to it, and if not you need to just set the Query field to your generated UTM data. But this code has to work around an oddity of (bug in?) how the UriBuilder in .Net 4.8 works. The Query property returns the ? from the querystring when you read it, but when you set a new value you mustn't include the ? or it ends up doubled up. This little LinqPad example shows that:

LinqPad showing example code for how UriBuilder incorrectly handles the '?' in querystrings

This has been fixed in the .Net Core version of this object, but we have to handle it here alas.

So once that code is in place and you've published the item change to add the custom class for the feed, the changes it makes to the data will be reflected in your feed:

An example RSS feed showing UTM fields added to the querystrings of the feed items

Success.

↑ Back to top