Sitecore and Cloudflare: Creating a Pipeline to Purge Cache on Publish

Master the process of building a Sitecore-Cloudflare pipeline to purge cache on publish for fast and efficient content updates.

April 24, 2023

By Gorman Law

This post will guide you in creating a pipeline to purge your Cloudflare cache when publishing an item. With the pipeline, there is no need to manually purge the cache every time a change is authored.

Prerequisites

Please read my previous guide on purging the cache using C#.

Next, you will need to create a new project called Website.Foundation.Helpers. You can name it whatever you want.

Create a new pipeline

Create a new .config file inside your App_Config folder (e.g., App_Config/Include/Project) and place the following code inside. I named mine PurgeOnPublish.

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <publish>
        <processor patch:after="*[@type='Sitecore.Publishing.Pipelines.Publish.ProcessQueue, Sitecore.Kernel']" type="Website.Foundation.Helpers.Cloudflare.CloudflarePurge, Website.Foundation.Helpers"/>
      </publish>
    </pipelines>
  </sitecore>
</configuration>

Next, create the classes from my previous blog (just copy and paste them). Create CloudflareCacheHelper, CloudflareFileInfo, and CloudflareResponse

Create the class that the pipeline runs

You will notice in the config file we named it Cloudflare purge, so create a new file named CloudflarePurge.cs that extends PublishProcessor. The following code will purge the cache. Read the comments for more details.

public class CloudflarePurge : PublishProcessor
{

    //process is the function that gets called
    public override void Process(PublishContext context)
    {
        Assert.ArgumentNotNull(context, "context");

        if (context.Aborted)
            return;

        //new helper instance
        CloudflarePurgeHelper cfPurge = new CloudflarePurgeHelper();

        //Fetches list of processed items (Created/Updated/Deleted) 
        var processedItems = context.ProcessedPublishingCandidates.Keys.Select(x => context.PublishOptions.TargetDatabase.GetItem(x.ItemId)).Where(y => y != null);

        //Create a list of links to purge
        List<string> linksToPurge = new List<string>();

        //Loop through each item
        foreach(var item in processedItems)
        {
            //if the item has a layout, it means it is an actual webpage.
            //You can add more checks here to see if it is part of your content tree
            if (HasLayout(item))
            {
                //The following code is just to get the full link of the item
                var siteContext = ResolveSiteContext(item);

                var options = LinkManager.GetDefaultUrlOptions();
                options.AlwaysIncludeServerUrl = true;
                options.SiteResolving = true;

                if(siteContext != null)
                {
                    options.Site = siteContext;
                }

                string link = LinkManager.GetItemUrl(item, options);

                //add the link to the list
                linksToPurge.Add(link);

            }
            //if the item isn't an actual webpage, just skip it
        }

        //send links to the purge function you already created
        if(linksToPurge.Count > 0)
        {
            //you can use this bool for your own purposes, or just leave it alone
            bool success = cfPurge.Purge(linksToPurge);
        }
    }

    private bool HasLayout(Item item)
    {
            return item.Visualization.Layout != null;
    }

    private SiteContext ResolveSiteContext(Item item)
    {
        string siteName = null;
        // loop through all configured sites
        foreach (var site in Sitecore.Configuration.Factory.GetSiteInfoList())
        {
            // get this site's home page item
            var sitePath = (site.RootPath + site.StartItem).ToLower();
            var itemPath = item.Paths.FullPath.ToLower();

            if (!String.IsNullOrWhiteSpace(sitePath) && itemPath.Contains(sitePath))
            {
                siteName = site.Name;
                break;
            }
        }
        return siteName == null ? null : SiteContext.GetSite(siteName);
    }
}

Conclusion

Cloudflare is an amazing service that makes defending and speeding your website easy. However, it can be annoying to have to manually purge the page after the smallest change. Hopefully, this blog can help alleviate some of your frustrations and speed up your workflow. Thanks for reading!!



Gorman Headshot

Gorman Law

Full Stack Developer

Gorman is a Full Stack Developer and a University of Calgary alumni who has a background in Canada's financial industry. Outside of work, he likes to go rock climbing, try out new ice cream places, and watch sports.

Second CTA Ogilvy's Legacy

Today, David Ogilvy's influence can still be felt in the world of advertising.

Ogilvy's Influence Example
Emphasis on research Market research is a crucial part of any successful advertising campaign
Focus on headlines A strong headline can make the difference between an ad that is noticed and one that is ignored
Use of visuals Compelling images and graphics are essential for capturing audience attention