Hiding Port in URLs Produced Sitecore’s LinkManager


There are many steps developers should take to make the most SEO-friendly web pages. One such task would be embedding a canonical URL tag. If you’re not familiar, it’s a tag included in the head of the HTML document that informs search engines what the definitive URL for a page should be.

<link rel="canonical" href="https://www.example" />

This is especially important on a Sitecore site’s because multiple URLs can reference the same piece of content. Between case insensitivity, swapping spaces for dashes and other mechanics, it’s possible to produce numerous combinations.

  • https://www.example.com/awesome-page
  • http://www.example.com/Awesome%20Page

By default, Sitecore creates URLs for links through the LinkManager and LinkProvider.  For consistency, all URLs should be produced that way.  To implement the contents of a canonical tag, you might have code like this:

        public string GetFullUrl(Item item)
            var urlOptions = LinkManager.GetDefaultUrlOptions();
            urlOptions.AlwaysIncludeServerUrl = true;
            urlOptions.SiteResolving = true;

            return LinkManager.GetItemUrl(item, urlOptions);

In most cases, that’s all you need and you’ll likely test it on your local, integration and staging environments before ever noticing any strange behavior. But in a robust production environment, there may be a few extra measures you need to take.

Things Get Complicated

In my company’s case, our applications are hosted on load-balanced content-delivery servers behind a WAF (web application firewall). For a recent client, we actually implemented “end-to-end encryption” which means the HTTP requests and responses are under SSL not just between the client browser and WAF, but between the WAF and the web servers as well. When that happens, the original URL is actually transformed, changing https://www.example.com/awesome-page to https://www.example.com:443/awesome-page. With no other code or configuration changes, the above code to produce an absolute URL for our canonical tags continues to include the port number “443”.

A knee-jerk reaction would be to include some special logic in your code to scrape the “:443” out of the URL before it’s returned. And you wouldn’t be alone in think that’s a good idea. I personally would suggest against that because it’s targeting a specific scenario that can only be recreated in certain environments. Sitecore might tend to agree since this can actually be solved with configuration.


You may already be familiar with the <site> node inside the Web.config or Sitecore.config (depending on your version). Many of the options are obvious and essential (ex. “hostName”) but others are more seldom used. Many of Sitecore’s defaults handle the most common case but there’s some mystery about how they work. In our case, we actually had to do something expected. Here’s a mock configuration patch.

    <site name="website">
        <patch:attribute name="scheme">https</patch:attribute>
        <patch:attribute name="externalPort">80</patch:attribute>

The scheme attribute makes sense since we want all of our URLs to use “https:”. However, if we’re using SSL, why is the port set to “80”? Turns out, Sitecore has explicit code looking for that value and, if it finds it, doesn’t include the port in the generated URL. In other words, setting externalPort to 80 is the same as saying “ignore the port”. From our experience, this was the only way to get the behavior we were after.


When dealing with variations between environments, the best practice should be to control those variations through configurations. Luckily, much of Sitecore’s behavior can be modified this way. Unfortunately, not every modification is perfectly documented and you may need to practice some “trial and error” before you find the ideal settings for your application. Hopefully, this post helps out a few people working through Sitecore behaviors. If you have other solutions, please feel free to post comments below.

Leave a Reply