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

Paul Gruffydd
Apr 1, 2019
  2848
(6 votes)

Future-proof your URLs with emojis

They say a picture paints a thousand words and, in our fast-paced world, who’s really got time to read a thousand words? Indeed, it would seem that even the 160 characters of a text message is a struggle for some these days leading to the creation of a whole new language - Emoji. But why should text messages have all the fun while web sites are stuck in the past?

Imagine a world where a website’s cookie policy could have the URL /🍪 rather than /cookies. This not only shrinks the URL to something memorable but also removes any language barriers as everyone can understand a picture regardless of the language they speak. In fact, even when languages should be the same there can be subtle differences which can cause problems. Imagine you ran an english language recipe site targeting the UK and US. You might have a URL like the following:
/recipes/tasty-aubergine-with-a-splash-of wine/

But in the US they don't use the word aubergine, they call it an eggplant so this would need to be rewritten to:
/recipes/tasty-eggplant-with-a-splash-of-wine/

If we were to write this in emoji we could have the following:
/👩‍🍳/😋🍆💦🍾/
Which, as you can see, is fun, concise, easy to remember and, most importantly, couldn’t possibly be misinterpreted.

Time to take a look at how we could do this in Episerver.

If we try to add an emoji without making any modifications, we get this.

This is due to the validation rules put in place by Episerver but, if the last couple of years have shown anything, it’s that us plucky Brits won’t just sit back and accept arbitrary rules put in place by unelected Europeans 😉. Time to take back control…

First we need to modify the rules for validating allowed characters in URL segments which we can do by overriding the UrlSegmentOptions in an IConfigurableModule.

[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class UrlInitialisation : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        //Enable emojis in URLs
        context.Services.RemoveAll<UrlSegmentOptions>();
        context.Services.AddSingleton<UrlSegmentOptions>(s => new UrlSegmentOptions
        {
            Encode = true,
            ValidCharacters = @"\p{L}0-9\-_~\.\$\u00a9\u00ae\u2000-\u3300\ud83c\ud000-\udfff\ud83d\ud000-\udfff\ud83e\ud000-\udfff"
        });
    }


    public void Initialize(InitializationEngine context) {
        //TODO

    }

    public void Uninitialize(InitializationEngine context) {
        //TODO
    }
}

At this stage we can now add emojis to our URLs but I want to take it a step further and get Episerver to generate emoji URL segments. To do this, I’ve downloaded a set of emojis from here which I’ve modified to remove unnecessary info, make the keywords more relevant and to tidy up some of the keywords we’ll use for our replacements. The new format for the emojis is as follows:

[
  {
    "Character": "🧐",
    "Keywords": "monocle|stuffy|rees-mogg"
  },
  {
    "Character": "💩",
    "Keywords": "dung|turd|poo|poop|brexit"
  }

]

Next, I load that into a collection of .net objects using json.net and build a dictionary mapping words to their emoji replacement. Then finally I’ve hooked in to the IUrlSegmentCreator’s Created event where I loop through the dictionary replacing any words I can.

Putting it all together we get this:

[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class UrlInitialisation : IConfigurableModule
{
    private Injected<IUrlSegmentCreator> _urlSegmentCreator;
    private Dictionary<string, string> _emojis = new Dictionary<string, string>();

    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        //Enable emojis in URLs
        context.Services.RemoveAll<UrlSegmentOptions>();
        context.Services.AddSingleton<UrlSegmentOptions>(s => new UrlSegmentOptions
        {
            Encode = true,
            ValidCharacters = @"\p{L}0-9\-_~\.\$\u00a9\u00ae\u2000-\u3300\ud83c\ud000-\udfff\ud83d\ud000-\udfff\ud83e\ud000-\udfff"
        });
    }


    public void Initialize(InitializationEngine context) {
        SetupEmojis();
        _urlSegmentCreator.Service.Created += CreateUrlSegment;

    }

    public void Uninitialize(InitializationEngine context) {
        _urlSegmentCreator.Service.Created -= CreateUrlSegment;
    }

    private void CreateUrlSegment(object sender, UrlSegmentEventArgs e)
    {
        foreach (var keyword in _emojis.Keys.OrderByDescending(x => x.Length))
        {
            //TODO: Remove stop words
            e.RoutingSegment.RouteSegment = e.RoutingSegment.RouteSegment.Replace(keyword, _emojis[keyword]);
        }
        //remove dashes
        e.RoutingSegment.RouteSegment = e.RoutingSegment.RouteSegment.Replace("-", "");
    }

    private void SetupEmojis()
    {
        var emojis = JsonConvert.DeserializeObject<List<EmojiInfo>>(File.ReadAllText(HttpContext.Current.Server.MapPath(@"/App_Data/emojis.json")));
        foreach (var emoji in emojis)
        {
            foreach (var keyword in emoji.KeywordList)
            {
                if (!_emojis.ContainsKey(keyword))
                {
                    _emojis.Add(keyword, emoji.Character);
                }
                var plural = keyword + "s";
                if (!_emojis.ContainsKey(plural))
                {
                    _emojis.Add(plural, emoji.Character);
                }
            }
        }
    }
}

public class EmojiInfo
{
    private IEnumerable<string> _keywordList = null;
    public string Character { get; set; }
    public string Keywords { get; set; }

    public IEnumerable<string> KeywordList
    {
        get
        {
            return _keywordList ?? Keywords.Split('|').Select(x => x.Replace(" ","-"));
        }
    }
}

So, why not join the 😎 kids and add emojis to your URLs today or are you 🕑😰?

Apr 01, 2019

Comments

KennyG
KennyG Apr 1, 2019 01:39 PM

I was waiting for the April Fool's punchline.

Paul Gruffydd
Paul Gruffydd Apr 2, 2019 08:50 AM

👍😉

Jake Jones
Jake Jones Apr 2, 2019 03:36 PM

Enjoyed the subtle Brexit references! 🧐

Paul Gruffydd
Paul Gruffydd Apr 2, 2019 05:17 PM

Ah, you spotted that. I thought I'd hidden it well 🕵️‍♂️. When I was writing this, I'd gone to some news sites for inspiration on story titles which could be comically misinterpreted in emoji form but all of them had nothing but brexit hence it creeping in there 😁.

Please login to comment.
Latest blogs
Looking back at Optimizely in 2025

Explore Optimizely's architectural shift in 2025, which removed coordination cost through a unified execution loop. Learn how agentic Opal AI and...

Andy Blyth | Dec 17, 2025 |

Cleaning Up Content Graph Webhooks in PaaS CMS: Scheduled Job

The Problem Bit of a niche issue, but we are building a headless solution where the presentation layer is hosted on Netlify, when in a regular...

Minesh Shah (Netcel) | Dec 17, 2025

A day in the life of an Optimizely OMVP - OptiGraphExtensions v2.0: Enhanced Search Control with Language Support and Synonym Slots

Supercharge your Optimizely Graph search experience with powerful new features for multilingual sites and fine-grained search tuning. As search...

Graham Carr | Dec 16, 2025

A day in the life of an Optimizely OMVP - Optimizely Opal: Specialized Agents, Workflows, and Tools Explained

The AI landscape in digital experience platforms has shifted dramatically. At Opticon 2025, Optimizely unveiled the next evolution of Optimizely Op...

Graham Carr | Dec 16, 2025

Optimizely CMS - Learning by Doing: EP09 - Create Hero, Breadcrumb's and Integrate SEO : Demo

  Episode 9  is Live!! The latest installment of my  Learning by Doing: Build Series  on  Optimizely Episode 9 CMS 12  is now available on YouTube!...

Ratish | Dec 15, 2025 |

Building simple Opal tools for product search and content creation

Optimizely Opal tools make it easy for AI agents to call your APIs – in this post we’ll build a small ASP.NET host that exposes two of them: one fo...

Pär Wissmark | Dec 13, 2025 |