A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Torunn Surnflødt
Mar 21, 2025
  30
(0 votes)

Links in Optimizely Cms: A guide

In Optimizely CMS there are several ways to link to internal or external content using different property types, and there are several ways to render these properties. This can be confusing, so here is an overview to hopefully make it easier to choose the best option
We will also take a look at the "on page edit" functionality in this matter, and make sure the links are properly localized..

This article is based on Optimizely Cms 12 with razor views, and the Alloy solution is used for demonstration.

Choose the correct property type

First, we will map out the different property types available.

Link to pages

There are two options when creating a property for linking to other pages:
 

  • ContentReference:  A good option if there is no need for linking to external content. You can also limit which pagetype should be allowed, using annotation.
     
    public virtual ContentReference Link1 { get; set; }
  • Url: If you want a simple property for linking both internally and externally.

    public virtual Url Link2 { get; set; }

 

Images

  • Url with UIHint.Image: If you want a property for choosing an image, you can use the Url property with a UIHint.

    [UIHint(UIHint.Image)]
    public virtual Url Link3 { get; set; }
    The UIHint can also be used for the ContentReference type.

General links

  • LinkItem: If you want a property for adding a link to either internal or external content, the best option is LinkItem. This will give you some extra attributes, which is described later on.

    public virtual LinkItem Link5 { get; set; }
  • LinkItemCollection: If you want the possibility to add multiple links, like a link list, you can use LinkItemCollection:

    public virtual LinkItemCollection Link4 { get; set; }

 

Choose how to render the property

Now, when you have chosen the preferred property type, the next step is to choose the correct way to render the property.

Unformatted

The Url property can be rendered directly, with no formatting, but this will not give you a friendly url.

  • Url:
    <a href="@Model.CurrentPage.Link2">Link</a>

    Result:
    <a href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Link</a>

     
  • Url with UIHint for image:
    <img src="@Model.CurrentPage.Link3" width="50"/>

    Result:
    <img src="/link/6f97d70164be4681975690d8f8c05379.aspx" width="50">

 

Friendly urls and localization

To make sure you get a url which takes into account localization and gives you a user friendly url, you should use the UrlResolver in backend and the UrlHelper in the views. Here is how to do this for the different property types:

 

Razor views:

  • ContentReference:
    <a href="@Url.ContentUrl(Model.CurrentPage.Link1)">Link</a>

    Result: 
    <a href="/no/alloy-plan/">Link</a>

     
  • Url:
    <a href="@Url.ContentUrl(Model.CurrentPage.Link2.Uri.ToString())">Link</a>

    Result: 
    <a href="/en/alloy-plan/">Link</a>
     

  • Url with UIHint for image:
    <img src="@Url.ContentUrl(Model.CurrentPage.Link3.Uri.ToString())" width="50" />

    Result:
    <img src="/globalassets/pexels-binoculars.jpg" width="50">

     
  • LinkItem:
    <a href="@Url.ContentUrl(Model.CurrentPage.Link5.Href)">Link</a>

    Result:
    <a href="/en/alloy-plan/">Link</a>

 

  • LinkItemColleciton:

    You will have to loop through the items in the LinkitemCollection to render each item the same way as the LinkItem above

    <ul>
    @foreach (var link in Model.CurrentPage.Link4)
    {
     <li><a href="@Url.ContentUrl(link.Href)">Link</a></li>
    }
    </ul>

    Result:
    <ul>
    <li><a href="/en/alloy-plan/">Link</a></li>
    <li><a href="/en/alloy-track/">Link</a></li>
    </ul>

 

Backend:

  • For backend it will be similar, just use an instance of the urlResolver instead.

    UrlResolver _urlResolver;
    (…)
    var url = _urlResolver.GetUrl(startPage);

 

LinkItem

Let's take a closer look at the LinkItem property. Previously, it was only available as part of the LinkItemCollection and could not be used independently. It is now available as a standalone property type, which is very convenient. The Url property gives you a simple way to add a url, whereas the LinkItem lets you store information such as text, target and link attributes. It also provides these methods:

 

  • GetMappedHref():

    /link/fdac9c5f86b64223b4a6397fe72483f9.aspx

     
  • ToMappedLink():

    <a title="Link to Alloy Plan" href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Read more about Alloy Plan</a>

     
  • ToPermanentLink():

    <a title="Link to Alloy Plan" href="~/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Read more about Alloy Plan</a>

None of these gives you a friendly or localized url though.

 

On page edit

The on page edit is a useful mode for the editor, so you should put in some effort to make it function properly.

There are three different ways to add this functionality:

 

  1. The good old "@Html.PropertyFor"
     
  2. The newer version "epi-property"
     
  3. And the helpful "@Html.EditAttributes" which can come into rescue where the above mentioned is not sufficient

 


All of them gives the same on page edit functionality. Example of the three options used with the Url property:

 

  1. @Html.PropertyFor(x => Model.CurrentPage.Link2)
  2. <a href="@Model.CurrentPage.Link2" epi-property="@Model.CurrentPage.Link2">Link</a> 
  3. <a href="@Model.CurrentPage.Link2" @Html.EditAttributes(x => Model.CurrentPage.Link2)>Link</a>


Now, there are some differences to the rendered markup. Number 2 and 3 will give you a simple link:


<a href="/link/fdac9c5f86b64223b4a6397fe72483f9.aspx">Link</a>

 

But number 1 will gives you significantly more out of the box. It provides a friendly url, automatically uses the page name as the link text, and ensures the link is properly localized for the correct culture.

<a href="/en/alloy-plan/">Alloy Plan</a>


Lets check out another example - the LinkItemCollection. As you remember from earlier, you had to manually loop through the items and render them one by one. If you want a simpler solution, you can use the Html.PropertyFor.


@Html.PropertyFor(x => Model.CurrentPage.Link4)


This will create the following markup:

<ul>
<li>
<a href="/en/alloy-plan/" title="Link to Alloy Plan">Read more about Alloy Plan</a>
</li>
<li>
<a href="/en/alloy-track/" title="Link to Alloy Track">Read more about Alloy Track</a>
</li>
</ul>

 

So the Html.PropertyFor gives you a full markup with on page edit and properly localized urls. Pretty nice - but there is one drawback. You don't have any control of the markup, regarding e.g. adding css classes.

 

Absolute Url

Often, you will need an absolute url, not just a relative one.  To achieve this, you can combine the relative url you have obtained using one of the methods mentioned earlier, with the site url:

 

var siteUrl = SiteDefinition.Current.SiteUrl.AbsoluteUri.TrimEnd('/');
var absoluteUrl = string.Concat(siteUrl, url);

 

This gives you an absolute url: https://localhost:5080/en/alloy-plan/

 

Summary

We have looked at different property types for creating link properties in Optimizely Cms 12:
 

  • The ContentReference is for linking to an internal page
  • The Url and the LinkItem can be used for linking internally or externally, where the latter lets you apply attributes like text, title and target
  • The Url with a UIHint annotation will let you link to media
  • The LinkItemCollection is convenient when you need multiple links

 

We looked at different ways to render each property type:

  • Unformatted: works for the Url property
  • Friendly, localized url: obtained using the UrlHelper for frontend and UrlResolver for backend
  • On page edit: different ways of rendering while maintaining the on page edit functionality


Finally, we looked at different ways to maintain the on page edit functionality for these property types.

  • @Html.PropertyFor
  • epi-property
  • @Html.EditAttributes

 

I hope this was helpful! Please let me know if you have any feedback.

Mar 21, 2025

Comments

Please login to comment.
Latest blogs
A day in the life of an Optimizely OMVP: Learning Optimizely Just Got Easier: Introducing the Optimizely Learning Centre

On the back of my last post about the Opti Graph Learning Centre, I am now happy to announce a revamped interactive learning platform that makes...

Graham Carr | Jan 31, 2026

Scheduled job for deleting content types and all related content

In my previous blog post which was about getting an overview of your sites content https://world.optimizely.com/blogs/Per-Nergard/Dates/2026/1/sche...

Per Nergård (MVP) | Jan 30, 2026

Working With Applications in Optimizely CMS 13

💡 Note:  The following content has been written based on Optimizely CMS 13 Preview 2 and may not accurately reflect the final release version. As...

Mark Stott | Jan 30, 2026

Experimentation at Speed Using Optimizely Opal and Web Experimentation

If you are working in experimentation, you will know that speed matters. The quicker you can go from idea to implementation, the faster you can...

Minesh Shah (Netcel) | Jan 30, 2026