This post isn’t a Sitecore only post. I faced a problem today, when one of my colleagues told me that one of the latest sites we had launched contained multiple title tags in the head part of the page, and one of the tags was empty!

It seemed crucial to solve because if a search engine should come by the page, you could be so unlucky that it would index the empty tag, instead of the filled one. Besides that, its invalid markup, so it needed to be fixed.

The rendered markup would look something like this: 

  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>My Title</title>

Our normal setup of the main layout in Sitecore contains of an aspx page, which includes a sublayout, which handles the meta tags called SEO.ascx.

My first thought was that the title tag had been defined on the aspx, and then again, in the SEO.ascx, this should be an easy one to solve. As I digged into it, it wasn’t the case. I also wasn’t able to locate anywhere in our codebase that was writing to the meta tags, which kept me confused.

The markup will look a lot like this (all custom has been removed)


<!DOCTYPE html>
  <head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <sc:Sublayout runat="server" Path="/layouts/SEO.ascx"/>
  <form method="post" runat="server" id="mainform">


<title>My Title</title>

After a while, and I had almost given up on this, I tried to remove the runat=”server” on the head tag. The tag isn’t really used in any of our code, and it handles that you can access some header properties from code behind, like Page.Title. It seemed to do the trick.

What actually happens is that when you have a runat=”server” on your head part of the page, ASP.NET is kind enough to add the title tag, if it can’t detect that you have handled it yourself! As you have guessed, it can’t figure it out, when write the tag in a sublayout. Had we done it via code behind in the sublayout, like  

this.Page.Title = "My Title";

The problem wouldn’t have been there, as ASP.NET gets this.

So the left is the question of why we had the runat=”server” in the first place on our aspx page; reason: Visual Studio defaults to this when you create a new aspx page, and no one ever noticed (until now)