Theme:

Doing Great SEO With Umbraco: Can We Toast Yoast?

Tagged with:
Accessibility
SEO
Nearly every person I talk to that's moving from WordPress to Umbraco has the same question: "How do we do SEO?"

For better or worse, WordPress is undeniably the most popular content management system in the world. The numbers vary depending on the source, but in the CMS space, WordPress has nearly a two-thirds market share. This means that there are a lot of content creators, editors, and marketers out there for whom WordPress is the only thing that they've used. It's the base reference by which everything else will be judged.

For Umbraco, this is mostly good news. While the WordPress editor experience has gotten much better in recent years, it still doesn't hold a candle to the ease of use of a well-configured Umbraco instance. There are two comments I get a lot when talking with new Umbraco editors coming from WordPress. The first is, "Wow, this is great!" But the second is, "Where's Yoast?"

Launched all the way back in 2008, Yoast SEO is one of the most popular WordPress plugins, and that's because it's very good at what it does. WordPress is not great at SEO out of the box; most of the content is not semantic or modeled, so the CMS can't really know what's an event vs an article vs a bio. Because of this, a lot of themes and templates don't really make the most of page content from an SEO perspective. Yoast gives editors the tools to cover for this, and it does so in a way that even less technical users feel like they're able to take charge of their site optimization. While you can't bring Yoast to Umbraco (and I've been asked that a lot), you can provide your Umbraco editors with a great SEO experience that makes them feel empowered to tackle their optimization needs.

Here are a few ways to provide a great and feature-rich SEO solution in Umbraco.

Model the Content Well, And It's Automatic

Ironically, one of the reasons our WordPress-using friends like Yoast so much is that they have to use it a lot. The default WordPress model gives you only two things: Posts and Pages (there are ways around this, but most sites just use these). If you make a page about a product, or an event, or anything else, you need to either use a plugin, or the CMS doesn't really know anything about the page. And because this semantic knowledge isn't part of the core product, there's no consistent way to handle it across the WP ecosystem. Editors feel like Yoast is solving a lot of problems for them, and it is, but a lot of those problems are created by the lack of a content model in WordPress.

In Umbraco, we're starting from a better place. Every time we create a new document type, we specifically define what the page is for and what types of fields it uses. This means that the CMS has context for all of this, so a lot of our SEO can be handled automatically.

With tools like Block Grid and Block List, it's tempting to just make a 'Generic Page' document type, and let the editors use it for everything (and this is always a good fallback). But for your structured pages (documents that are "about" something - a product, a bio, an article, etc), it's better to provide specific fields. A big reason for this is that it's easier and more consistent for editors to use, but another big reason is to take advantage of Structured Data Markup.

Structured Data Markup provides machine-readable data in your page that helps search engines really understand what the page is about, not just what it says. Search engines use this to better target results, and to display Rich Results, which incorporate some of the information directly in the search results, making your listing stand out.

Screenshot of a Google search result page displaying recipes with images in a list of tiles.

With the right information, search engines will provide information-rich results that make your listing stand out.

There's a massive and constantly growing list of schema that defines the standards for marking up various concepts, like organizations, people, products, services, recipes, etc. Practically speaking, I recommend focusing on the standards that Google already supports. You can embed structured data in your pages and components using microdata or RDFa attributes, but I find that the easiest way to add them is using JSON-LD, which allows you to define javascript value object in your page to enhance machine readability.

For instance, if I define a page type in Umbraco that will display a user profile, I will probably include fields for things like a person's name, company, title, and image in the document type. In addition to my normal human UI on my template, I can also include a JSON structure like this:


<script type="ld+json">
    {
      "@context": "https://schema.org",
      "@type": "ProfilePage",
      "mainEntity": {
        "@type": "Person",
        "name": "Joe Kepley",
        "identifier": "joe-kepley",
        "jobTitle": "CTO",
        "affiliation": {
          "@type":"Organization",
          "name":"Blend Interactive",
          "url":"https://blendinteractive.com"
        }
        "image": "https://example.com/avatars/joe.jpg",
      },
      "dateCreated": "2024-12-23T12:34:00-05:00",
      "dateModified": "2024-12-26T14:53:00-05:00"
    }
</script>

Using a library like Schema.NET in your controllers or templates makes generating these pretty simple. You can also use this for page elements like breadcrumbs and footers, and even include partial schema data in elements of the block list or block grid. Read through Google's Documentation for guidance on how to best use each type of schema to help deliver Rich Results.

Structured Data, along with OpenGraph Properties and our old friends the meta title and description, provide a tremendous amount of SEO value without our editors needing to do anything at all.

I'd also recommend including specific fields for SEO, but providing reasonable defaults that will be used if SEO fields aren't filled in. For instance, your logic for your page's OpenGraph title (which informs how it appears on Twitter and Facebook), might look like this:

  • If the 'Sharing Title' field is filled in, use that. Else,
  • If the 'Meta Title' field is filled in, use that. Else,
  • Use the Content Object name

That way, editors can be specific if they want, but they'll have good defaults if they don't. We often like to require a field for a short summary and a main image. If you don't want to require these, you could always use a default image and the first couple of sentences of body copy as a fallback. We want to make good SEO as automatic as possible, but still give editors the controls they need in order to optimize manually.

Other things the CMS can handle for editors automatically are things like sitemaps, robots.txt files, and canonical links. There are a lot of good packages out there that handle these for us; there are a lot of good packages available for these things, so we'll talk about those in a bit.

Some Easy Quick Wins

There are a lot of subtle things we can do for editors that can help a lot with SEO. Here's a list of high-impact changes that are easy to miss when building a site, but are thankfully also pretty easy to correct:

Enforce a single URL through redirects

If you just use a default site setup, there may be a few valid URLs for every page, even if it only supposedly has one URL. Let's look at the URL for the 24 Days about page:

  • https://24days.in/umbraco-cms/about/
  • https://24days.in/umbraco-cms/about
  • https://www.24days.in/umbraco-cms/about/
  • https://www.24days.in/umbraco-cms/about

For that one URL, there are 4 valid URLs. Go ahead and multiply that by two if your site doesn't enforce HTTPS (you should really be enforcing HTTPS.)

Google doesn't have a good way to definitively know that these are all the same page, so all of the traffic and relevance scoring can wind up being split 4 ways across one page! Canonical URL tags help with this, but a simple web.config entry will help sort this out by enforcing a single preference for the URL. In this example we're preferring to use the apex (non-www) domain and include a trailing slash on URLs:


<rewrite><!-- add to the system.webServer block -->
  <rules>
    <rule name="RemoveWww" stopProcessing="true">
      <match url="(.*)" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{HTTP_HOST}" pattern="^www\.24days\.in" />
      </conditions>
      <action type="Redirect" 
        appendQueryString="false" 
        redirectType="Permanent" 
        url="https://24days.in{REQUEST_URI}" />
    </rule>
    <rule name="AddTrailingSlash" stopProcessing="true">
      <match url="^([^.]*[^/])$" /><!-- matches any URL where the last character isn't a slash -->
      <conditions><!-- We don't really mess with this for the backoffice or files not served by the CMS -->
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{URL}" pattern="umbraco(.*?)$" negate="true" />
        <add input="{URL}" pattern="umbidlocallogin(.*?)$" negate="true" />
      </conditions>
      <action type="Redirect" redirectType="Permanent" url="{R:1}/" />
    </rule>
  </rules>
</rewrite>

Use Good Alt Text

Lots of accessibility best practices are fortunately also SEO best practices (This is a great way to sell accessibility upgrades, BTW). I recommend adding an option for alt text to your Image media type in your Umbraco settings, but also adding alt text fields every place an image gets used, because context matters when it comes to good descriptions. Set your templates up to prefer the local alt text field, but use the one on the image if it's empty. On top of this, we use AltTextAI to automatically create alt text even during bulk image uploads. Editors can still override that, but it means we always have something. Again, we're trying to get the best result we can for the least work, but still give editors the control they need to tweak things later.

Allow Editors To Correct Heading Hierarchy

One of the challenges with assembling pages from components with block lists and block grids can be maintaining a good heading hierarchy. A lot of your components might contain headings, or you might have a heading element. When these are arranged freeform on the page, the templated heading sizes might make visual sense, but not make logical sense, which makes it harder for automated systems to understand the page's outline. This is another case where good SEO is also good accessibility. To help with this, you can add options in your CSS and in your Umbraco model to allow editors to define a visual heading style and the heading tag to use separately. That way, they can get the visual look they're going for and still maintain a proper heading hierarchy (as always, set it up so the defaults work most of the time).


<!-- In a default Bootstrap setup, these will  appear to be the same visually -->

<h3>Third-Level Heading</h3>

<h2 class="h3">Second-Level Heading That Looks Like It's A Third Level</h2>

Brown Paper Packages Tied Up With String

We've talked about a lot of things you can do to provide a great SEO solution, but these are just the beginning. Editors love to have good, helpful tools that put them in control and help them to make the right decisions without necessarily being SEO experts. Fortunately, there are a lot of great Umbraco packages out there that can do precisely that.

SEOChecker

When editors ask me, "Is there a Yoast Pro for Umbraco?", I show them Richard Soeteman's SEOChecker. For an extremely reasonable one-time license fee, SEOChecker adds a ton of SEO capability to your Umbraco site. This includes:

  • Sitemaps
  • Robots.txt
  • Redirect Management
  • Validation and editor coaching for metadata
  • Search and Social Media Snippet Preview

and lots more. While it's not quite as robust as something like Yoast, it still provides an insane amount of value in an inexpensive package.

Screenshot of the Umbraco BackOffice. The SeoChecker plugin has added controls to preview search and social listings and provide red or green indicators for how well the page complies with a set of SEO checks.

SEOChecker adds a lot of helpful SEO control to your BackOffice

If you need a no-budget option that still aims to provide an all-in-one solution, have a look at SEOToolkit, which offers a number of the same base features, but doesn't offer editor guidance.

Roll Your Own

If you would prefer to compose your own solution, there are a number of packages that focus on delivering a single piece of the solution:

  • MetaMomentum and SEOVisualiser focus on managing share tags, with previews
  • Blend offers packages that handle sitemaps and robots.txt files
  • WonderSeoChecker embeds lighthouse performance analysis into the Umbraco BackOffice
  • Similarly, AccessibilityReporter provides a robust accessibility report directly in the BackOffice. Not exactly an SEO-focused tool, but again, good accessibility often makes for good SEO, and vice versa

Good accessibility and good SEO go together. AccessibilityReporter is an easy drop-in that's useful on almost any site.

External Services

Finally, there are a lot of subscription services that offer third-party SEO reporting for your site. A lot of the more popular ones have packages that bring their findings right into the BackOffice to streamline your workflow:

Little Things Make a Lot of Difference

Often, good SEO is invisible. You can implement all of the tips in this article and wind up with a page that looks exactly the same to the casual observer. But this is all the more reason to make sure that your builds are performant, accessible, and SEO-friendly. It's time to show all your Yoast-loving editors that you can achieve high-quality SEO results with even less work!