<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blogs</title> <link>https://world.optimizely.com/blogs/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>Forcing Lowercase URLs in Optimizely CMS During Auto-Translation</title>            <link>https://stuartgreig.dev/blog/forcing-lowercase-urls-in-optimizely-cms-during-auto-translation/</link>            <description>Learn how to fix uppercase and punctuation issues in Optimizely CMS 12 URL segments caused by LanguageManager auto-translation using a custom IUrlSegmentGenerator and event-based tracking.</description>            <guid>https://stuartgreig.dev/blog/forcing-lowercase-urls-in-optimizely-cms-during-auto-translation/</guid>            <pubDate>Thu, 02 Apr 2026 15:15:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>Stott Robots Handler v7 for Optimizely CMS 13</title>            <link>https://world.optimizely.com/blogs/mark-stott/dates/2026/4/stott-robots-handler-v7-for-optimizely-cms-13/</link>            <description>&lt;p&gt;Stott Robots Handler version 7 is now available for&amp;nbsp;&lt;strong&gt;Optimizely PaaS CMS 13&lt;/strong&gt;. This is includes updates to support the switch from a Site based architecture to an Application based architecture.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.stott.pro/assets/robots-handler-v7.png&quot; alt=&quot;Robots Handler V7 initial interace&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;How does the change from Sites to Applications impact the user?&lt;/h2&gt;
&lt;p&gt;The data structure of Applications is subtly different to that of Sites. In CMS 12, sites were uniquely identified using a GUID. In CMS 13, Applications are uniquely identified using a string identifier. This breaks the relationship between existing robots.txt and llms.txt content and the sites they were configured to serve.&lt;/p&gt;
&lt;p&gt;Users will have to reconfigure their robots.txt and llms.txt content when moving from CMS 12 to CMS 13. The content for both files is stored in the Dynamic Data Store and is matched to an active application before being displayed to the CMS Administrator or being served to end users.&lt;/p&gt;
&lt;p&gt;The Environment Robots and the API Tokens are global configurations and are not bound to a specific site or application. When upgrading to version 7 and CMS 13, these features will retain their existing configuration.&lt;/p&gt;
&lt;h3&gt;What features does Stott Robots Handler have?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&#129302; Manage robots.txt content by Application and specific Host URL&lt;/li&gt;
&lt;li&gt;&#128196; Manage llms.txt content by Application and specific Host URL&lt;/li&gt;
&lt;li&gt;&#128274; Override robots meta tags and response headers at an environment level to prevent indexing lower environments in search engines.&lt;/li&gt;
&lt;li&gt;&#127760; APIs to support headless solutions&lt;/li&gt;
&lt;li&gt;&#127760; APIs to support modification of robots.txt and llms.txt content directly within Optimizely Opal&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What does this mean for Optimizely CMS 12?&lt;/h2&gt;
&lt;p&gt;Support for version 6 of the Stott Robots Handler is not going away. New functionality will be developed directly for version 7 and then backported to version 6 where appropriate. I can review the recent download stats on a version by version basis on nuget and I will use this as an indicator of the current market need.&lt;/p&gt;
&lt;p&gt;I expect that it will take a few years for a significant portion of customers to move from CMS 12 to CMS 13. Therefore, I expect to maintain the CMS 12 version for the short to mid term.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Stott Robots Handler v7 is available for&amp;nbsp;&lt;strong&gt;Optimizely PaaS CMS 13&lt;/strong&gt; on nuget.org and on api.nuget.optimizely.com. You can see the full installation instructions and package information over on the &lt;a href=&quot;https://github.com/GeekInTheNorth/Stott.Optimizely.RobotsHandler&quot;&gt;github page&lt;/a&gt;, including how to configure the add-on for use with Opti Id.&lt;/p&gt;
&lt;p&gt;Getting started can be as simple as:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;// Install the nuget package
dotnet add package Stott.Optimizely.RobotsHandler

// Add this to your services
services.AddRobotsHandler();

// Add this to your configure method
services.UseRobotsHandler();

// Add this to your _ViewImports.cshtml if you are running traditional
@addTagHelper *, Stott.Optimizely.RobotsHandler&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;I am an OMVP and the author and maintainer of&amp;nbsp;&lt;a title=&quot;Stott Security&quot; href=&quot;https://github.com/GeekInTheNorth/Stott.Security.Optimizely&quot;&gt;Stott Security&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a title=&quot;Stott Robots Handler&quot; href=&quot;https://github.com/GeekInTheNorth/Stott.Optimizely.RobotsHandler&quot;&gt;Stott Robots Handler&lt;/a&gt;&amp;nbsp;for Optimizely CMS 12. You can find all of my content collated on&amp;nbsp;&lt;a title=&quot;The blog website for Mark Stott.&quot; href=&quot;https://www.stott.pro/&quot;&gt;https://www.stott.pro/&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/mark-stott/dates/2026/4/stott-robots-handler-v7-for-optimizely-cms-13/</guid>            <pubDate>Thu, 02 Apr 2026 09:44:40 GMT</pubDate>           <category>Blog post</category></item><item> <title>Automating Block Translations in Optimizely</title>            <link>https://stuartgreig.dev/blog/automating-block-translations-in-optimizely/</link>            <description>Stop manual block-by-block translations. Learn how to use the TranslateOrCopyContentAreaChildrenBlockForTypes config to automate Optimizely CMS content workflows.</description>            <guid>https://stuartgreig.dev/blog/automating-block-translations-in-optimizely/</guid>            <pubDate>Wed, 01 Apr 2026 16:00:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>How to Disable automatic indexing in Optimizely Search &amp; Navigation</title>            <link>https://www.gulla.net/en/blog/how-to-disable-automatic-indexing-in-optimizely-search-and-navigation/</link>            <description>Learn how automatic event-based indexing works in Optimizely Search &amp; Navigation and how you can temporarily disable it.</description>            <guid>https://www.gulla.net/en/blog/how-to-disable-automatic-indexing-in-optimizely-search-and-navigation/</guid>            <pubDate>Wed, 01 Apr 2026 07:11:38 GMT</pubDate>           <category>Blog post</category></item><item> <title>Fixing “Published By” After OKTA SSO in Optimizely CMS</title>            <link>https://world.optimizely.com/blogs/sanjay-katiyar/dates/2026/3/making-published-by-readable-after-okta-sso/</link>            <description>&lt;p&gt;Enabling &lt;strong&gt;Okta SSO&lt;/strong&gt; significantly strengthened our authentication and security model in &lt;strong&gt;Optimizely CMS&lt;/strong&gt;. However, like many real-world implementations, it also introduced an unexpected challenge in the CMS authoring experience, as the system now stores the Okta ID as the username.&lt;/p&gt;
&lt;h3&gt;Problem:&lt;/h3&gt;
&lt;p&gt;After switching to SSO, we observed a change in how user identities were stored:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;&amp;ldquo;Published By&amp;rdquo;&lt;/strong&gt; field displayed Okta ID&lt;/li&gt;
&lt;li&gt;Instead of names or emails, editors saw technical IDs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;img src=&quot;/link/05ea94f3777042d884546a3497a28641.aspx&quot; width=&quot;472&quot; height=&quot;265&quot; /&gt;&lt;br /&gt;&lt;br /&gt;Impact on Editorial Exp.&lt;/h3&gt;
&lt;p&gt;This created friction for content teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Author attribution became unclear&lt;/li&gt;
&lt;li&gt;Content review was harder to follow&lt;/li&gt;
&lt;li&gt;Auditing lost its human-readable context&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For non-technical users, this was a noticeable drop in usability.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;Solution:&lt;/h3&gt;
&lt;p&gt;To address this, we introduced a custom transformation:&lt;/p&gt;
&lt;h3&gt;&#128073; PublishedByTransform&lt;/h3&gt;
&lt;p&gt;This transform maps the stored Okta identifier to a &lt;strong&gt;friendly display value&lt;/strong&gt;, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Author name&lt;/li&gt;
&lt;li&gt;Email address&lt;/li&gt;
&lt;li&gt;Or any readable identity field&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of exposing raw Okta IDs, the CMS now resolves and displays meaningful user information.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt; [ServiceConfiguration(typeof(IModelTransform), Lifecycle = ServiceInstanceScope.Singleton)]
 public class PublishedByTransform : ContentDataStoreModelTransform
 {
     private readonly EPiServer.Logging.ILogger _logger;
     private readonly IUserService _userService;
     private readonly IPrincipalAccessor _principalAccessor;
     private readonly IContentVersionRepository _contentVersionRepository;

     public PublishedByTransform(
         IUserService userService,
         IPrincipalAccessor principalAccessor,
         IContentVersionRepository contentVersionRepository)
     {
         _userService = userService ?? throw new ArgumentNullException(nameof(userService));
         _principalAccessor = principalAccessor ?? throw new ArgumentNullException(nameof(principalAccessor));
         _contentVersionRepository = contentVersionRepository ?? throw new ArgumentNullException(nameof(contentVersionRepository));
         _logger = LogManager.GetLogger(typeof(PublishedByTransform));
     }

     public override void TransformInstance(IContent source, ContentDataStoreModel target, IModelTransformContext context)
     {
         base.TransformInstance(source, target, context);
         ContentVersion contentVersion1 = this._contentVersionRepository.Load(source.ContentLink);
         ContentVersion contentVersion2 = _contentVersionRepository.LoadPublished(source.ContentLink, source.LanguageBranch());

         if (contentVersion1 != null)
         {
             var versionCreatedBy = string.IsNullOrEmpty(contentVersion1.StatusChangedBy) ? contentVersion1.SavedBy : contentVersion1.StatusChangedBy;
             target.VersionCreatedBy = ResolvePublishedBy(versionCreatedBy);
         }

         if (contentVersion2 != null)
         {
             var publishedBy = !string.IsNullOrWhiteSpace(contentVersion2.StatusChangedBy)
                 ? contentVersion2.StatusChangedBy
                 : contentVersion2.SavedBy;

             target.PublishedBy = ResolvePublishedBy(publishedBy);
         }
     }

     private string? ResolvePublishedBy(string? publishedBy)
     {
         if (string.IsNullOrWhiteSpace(publishedBy))
             return publishedBy;

         try
         {
             var user = _userService.GetUserByName(publishedBy);
             if (user == null)
                 return publishedBy;

             var claimsPrincipal = _principalAccessor.Principal as ClaimsPrincipal;
             var currentUserEmail = claimsPrincipal?.FindFirst(&quot;email&quot;)?.Value ?? claimsPrincipal?.FindFirst(ClaimTypes.Email)?.Value;
             if (!string.IsNullOrWhiteSpace(currentUserEmail)
                 &amp;amp;&amp;amp; !string.IsNullOrWhiteSpace(user.Email)
                 &amp;amp;&amp;amp; string.Equals(currentUserEmail, user.Email, StringComparison.OrdinalIgnoreCase))
             {
                 return &quot;you&quot;;
             }

             return !string.IsNullOrWhiteSpace(user.Email) ? user.Email : user.UserName;
         }
         catch (Exception ex)
         {
             _logger.Error($&quot;PublishedByTransform failed to resolve PublishedBy for value &#39;{publishedBy}&#39;. Error: {ex}&quot;);
             return publishedBy;
         }
     }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Result:&lt;/h3&gt;
&lt;p&gt;With this small but impactful enhancement, we achieved the best of both worlds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Secure SSO via Okta remains fully in place&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Published By&amp;rdquo; now shows clear, readable author names&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/link/47a5fce5e8994df8bb58a74b42abb0d4.aspx&quot; width=&quot;483&quot; height=&quot;310&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Thank you for reading the blog. Cheers!&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/sanjay-katiyar/dates/2026/3/making-published-by-readable-after-okta-sso/</guid>            <pubDate>Wed, 01 Apr 2026 04:54:06 GMT</pubDate>           <category>Blog post</category></item><item> <title>OptiPowerTools.Hangfire: A Drop-in Hangfire Integration for Optimizely CMS 12</title>            <link>https://szolkowski.github.io/2026/03/31/OptiPowerTools.Hangfire-A-Drop-in-Hangfire-Integration-for-Optimizely-CMS-12</link>            <description>Back in 2024, I wrote a post on Adding Hangfire to Episerver/Optimizely CMS 12, walking through each step of integrating Hangfire into an Optimizely project — the authorization filter, the controller, the view with an iframe, the menu provider, the startup wiring. It was a fair amount of boilerplate, but it worked and people found it useful.</description>            <guid>https://szolkowski.github.io/2026/03/31/OptiPowerTools.Hangfire-A-Drop-in-Hangfire-Integration-for-Optimizely-CMS-12</guid>            <pubDate>Tue, 31 Mar 2026 08:00:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>Upgrade Guide: Commerce 14 to Commerce 15 preview </title>            <link>https://world.optimizely.com/blogs/viet-anh-nguyen/dates/2026/3/upgrade-guide-commerce-14-to-commerce-15-preview-/</link>            <description>&lt;div class=&quot;SCXW92401041 BCX0&quot;&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;This document provides step-by-step instructions to upgrade a Commerce site from Commerce 14/CMS 12 to Commerce 15/CMS 13 preview.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Overview&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;This upgrade includes:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Commerce&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: 14.15.3 &amp;rarr; 15.0.0-preview1&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;CMS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: 12.31.2 &amp;rarr; 13.0.0-preview4&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;.NET&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: 8.0 &amp;rarr; 10.0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Prerequisites&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Visual Studio 2022 with .NET 10.0 SDK&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;SQL Server (&lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW92401041 BCX0&quot;&gt;LocalDB&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;nbsp;or full instance)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Basic understanding of Optimizely Commerce and CMS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Step 1: Create a new Commerce 14 empty site from template&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;To create a baseline Commerce 14 site from template:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul&gt;
&lt;li class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Run the template command:&lt;/span&gt;&lt;/span&gt; &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;dotnet new epi-commerce-empty --name CoCo14 --force&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Open the project, restore packages, and build it&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Press F5 and create a user by accessing:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/util/register&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/util/register&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Log in at:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/util/login&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/util/login&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Migrate Commerce data:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/episerver/commerce/migrate&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/episerver/commerce/migrate&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Verify the CMS/Commerce Admin UI:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/episerver/cms&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/episerver/cms&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Verification&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: Ensure the site is running without errors before&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;proceeding&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Step 2: Update Project Configuration&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;File Modified&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: [CoCo14.csproj]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Target Framework&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;TargetFramework&amp;gt;net10.0&amp;lt;/TargetFramework&amp;gt;  &amp;lt;!-- was net8.0 --&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Package References&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Before&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;(Simple metapackage approach):&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.CMS&quot; Version=&quot;12.31.2&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Commerce&quot; Version=&quot;14.15.3&quot; /&amp;gt; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;After&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;(Explicit package references):&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Commerce packages:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.Commerce&quot; Version=&quot;15.0.0-preview1&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;CMS packages (all version 13.0.0-preview4):&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.OptimizelyIdentity&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.CMS.UI.AspNetIdentity&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;Optimizely.Graph.Cms&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Cms.UI.ContentManager&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Hosting&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Cms.UI.VisitorGroups&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.CMS.Shell.UI&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.CMS.UI&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.ImageLibrary.ImageSharp&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Events.ChangeNotification&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Cms.AspNetCore.TagHelpers&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Cms.AspNetCore.HtmlHelpers&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt; 
&amp;lt;PackageReference Include=&quot;EPiServer.Cms.TinyMce&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Step 3: Update Startup Configuration&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;File Modified&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW92401041 BCX0&quot;&gt;Startup.cs&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Update Service Registration&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Before&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;(Commerce 14 - Simple metapackage registration):&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;services 
    .AddCmsAspNetIdentity&amp;lt;ApplicationUser&amp;gt;() 
    .AddCommerce() 
    .AddAdminUserRegistration() 
    .AddEmbeddedLocalization&amp;lt;Startup&amp;gt;(); &lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;After&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;(Commerce 15 - Explicit service registration):&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;services 
    .AddCmsHost() 
    .AddCmsCore() 
    .AddCmsAspNetIdentity&amp;lt;ApplicationUser&amp;gt;() 
    .AddCmsHtmlHelpers() 
    .AddCmsTagHelpers() 
    .AddCmsUI() 
    .AddAdmin() 
    .AddCmsImageSharpImageLibrary() 
    .AddTinyMce() 
    .AddContentGraph() 
    .AddContentManager() 
    .AddCommerce() 
    .AddVisitorGroupsMvc() 
    .AddVisitorGroupsUI() 
    .AddAdminUserRegistration() 
    .AddEmbeddedLocalization&amp;lt;Startup&amp;gt;(); 
 
services.Configure&amp;lt;DataAccessOptions&amp;gt;(options =&amp;gt; 
{ 
    options.UpdateDatabaseCompatibilityLevel = true; 
}); &lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Step 4: Update Application Settings&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;SCXW92401041 BCX0&quot;&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;File Modified&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW92401041 BCX0&quot;&gt;appsettings.json&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Add the following Optimizely configuration section for Content Graph&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&quot;Optimizely&quot;: { 
  &quot;ContentGraph&quot;: { 
    &quot;GatewayAddress&quot;: &quot;https://cg.optimizely.com&quot;, 
    &quot;AppKey&quot;: &quot;&amp;lt;app-key&amp;gt;&quot;, 
    &quot;Secret&quot;: &quot;&amp;lt;secret&amp;gt;&quot;, 
    &quot;SingleKey&quot;: &quot;&amp;lt;single-key&amp;gt;&quot;, 
    &quot;AllowSendingLog&quot;: &quot;true&quot; 
  } 
} &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;br /&gt;Important&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;: Replace the placeholder values (&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;lt;app-key&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;lt;secret&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;lt;single-key&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;lt;instance-id&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;) with your actual credentials from the Optimizely portal.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt; &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Step 5: Restore, Build, and Run Migration&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;After making all the changes:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Restore packages&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;dotnet restore&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Build the project&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;dotnet build&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Run the application&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul class=&quot;NumberListStyle2 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Press F5 in Visual Studio, or&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ol&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul class=&quot;NumberListStyle2 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Run&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;dotnet run&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;nbsp;from the command line&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Run Commerce migration&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ol&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul class=&quot;NumberListStyle2 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Navigate to:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/Optimizely/commerce/migrate&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/Optimizely/commerce/migrate&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ol&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul class=&quot;NumberListStyle2 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;This will update the database schema and migrate data to Commerce 15 format&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&lt;br /&gt;Step 6: Verify the Upgrade&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;NumberListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Access the Commerce Admin UI&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Navigate to &lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://localhost:5000/Optimizely/Commerce/&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;https://localhost:5000/Optimizely/Commerce/&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Important Notes&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;SCXW92401041 BCX0&quot;&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Code Compatibility&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Depending on your Commerce solution, you may need to update source code due to API changes in CMS 13 and Commerce 15. See the&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://docs.developers.optimizely.com/content-management-system/v13-Pre-Release/docs/overview-of-cms-13-pre-release&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;CMS 13 Pre-Release overview&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;nbsp;for details.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Commerce 15-compatible versions for popular Commerce add-ons will be released later&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Preview Versions&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Commerce 15.0.0-preview1&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;nbsp;and&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;CMS 13.0.0-preview4&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;&amp;nbsp;are pre-release versions&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Not recommended for production use&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Use for evaluation and testing purposes only&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Additional Resources&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://docs.developers.optimizely.com/commerce-connect/docs/creating-your-project&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;How to create an empty commerce project from which you can build your Optimizely Commerce Connect website&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;/link/401767d8a5e8446db6e213b139618c2d.aspx&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Official upgrade guide: CMS 12 to CMS 13&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ListContainerWrapper SCXW92401041 BCX0&quot;&gt;
&lt;ul class=&quot;BulletListStyle1 SCXW92401041 BCX0&quot;&gt;
&lt;li class=&quot;OutlineElement Ltr SCXW92401041 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW92401041 BCX0&quot;&gt;&lt;a class=&quot;Hyperlink SCXW92401041 BCX0&quot; href=&quot;https://docs.developers.optimizely.com/commerce-connect/v15-pre-release/docs/overview-of-commerce-15-pre-release&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW92401041 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW92401041 BCX0&quot;&gt;Overview of Commerce 15 pre-release&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;EOP SCXW92401041 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description>            <guid>https://world.optimizely.com/blogs/viet-anh-nguyen/dates/2026/3/upgrade-guide-commerce-14-to-commerce-15-preview-/</guid>            <pubDate>Tue, 31 Mar 2026 03:59:41 GMT</pubDate>           <category>Blog post</category></item><item> <title>Prove what your experimentation program is worth with Holdouts</title>            <link>https://world.optimizely.com/blogs/sarahs-blog/dates/2026/3/holdouts-available-in-feature-experimentation/</link>            <description>&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Running experiments is one thing. Knowing whether your experimentation program is moving the business forward?&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;That&#39;s&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;the harder question.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Most teams can point to individual test wins. A headline change that lifted click-through. A checkout flow that cut abandonment. But when leadership&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun ContextualSpellingAndGrammarErrorV2Themed SCXW65388752 BCX0&quot;&gt;asks&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: rgb(132, 63, 161);&quot;&gt;&quot;what is all this experimentation worth?&quot; t&lt;/span&gt;he answer gets complicated fast.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Today, that question gets a lot easier to answer. Holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;s&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun ContextualSpellingAndGrammarErrorV2Themed SCXW65388752 BCX0&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;now available in Optimizely&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Feature&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Experimentation.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;WACImageContainer NoPadding DragDrop BlobObject SCXW65388752 BCX0&quot;&gt;&lt;img class=&quot;WACImage SCXW65388752 BCX0&quot; src=&quot;/link/0c35057005d44245a72145e741073a65.aspx&quot; alt=&quot;Shape&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;h1 class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;span class=&quot;TextRun MacChromeBold SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;What Holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;s do&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span style=&quot;color: rgb(35, 111, 161);&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;s&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun ContextualSpellingAndGrammarErrorV2Themed SCXW65388752 BCX0&quot;&gt;reserves&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;a fixed percentage of your users from all running experiments. That group sees no test variants, no changes, nothing different.&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;They&#39;re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;your global control.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;At the end of a measurement period, you compare what happened to the holdout group against everyone else. The difference is the net lift of your entire experimentation program. Not one test. All of them.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;It&#39;s&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;the cleanest answer to the question every experimentation leader eventually faces:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&quot;What would have happened if we hadn&#39;t run any experiments at all?&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;WACImageContainer NoPadding DragDrop BlobObject SCXW65388752 BCX0&quot;&gt;&lt;img class=&quot;WACImage SCXW65388752 BCX0&quot; src=&quot;/link/0c35057005d44245a72145e741073a65.aspx&quot; alt=&quot;Shape&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;h2 class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;strong&gt;&lt;span class=&quot;TextRun MacChromeBold SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Why it matters for mature programs&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;If&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;you&#39;re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;running multiple experiments concurrently, individual test results only tell part of the story. Experiments interact. Variants overlap. And without a clean baseline,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;you&#39;re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;measuring performance against a constantly shifting target.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;s&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;fix that. It gives you an unbiased comparison point that sits outside your test traffic. The result is a measurement you can take to leadership with confidence.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Not a collection of test summaries. A defensible number that answers the question your CFO is asking.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&lt;img src=&quot;/link/6064597c2d804afb87facdbf5961afa3.aspx&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;1062&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;WACImageContainer NoPadding DragDrop BlobObject SCXW65388752 BCX0&quot;&gt;&lt;img class=&quot;WACImage SCXW65388752 BCX0&quot; src=&quot;/link/0c35057005d44245a72145e741073a65.aspx&quot; alt=&quot;Shape&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;h2 class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun MacChromeBold SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Built for the programs that need it most&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;This feature is designed for teams running at scale. If&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;you&#39;re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;running a handful of experiments a year, individual test metrics serve you well. But if your program spans multiple teams, products, and concurrent tests, Holdout Groups gives you the program-level view&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;you&#39;ve&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;been missing.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;And it works alongside your existing setup. No changes to individual experiments. No disruption to running tests. Just an&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;additional&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;layer of measurement that sits above everything&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;you&#39;re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;already doing.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;WACImageContainer NoPadding DragDrop BlobObject SCXW65388752 BCX0&quot;&gt;&lt;img class=&quot;WACImage SCXW65388752 BCX0&quot; src=&quot;/link/daf44faacccc41d3837e0c10f07f23c6.aspx&quot; alt=&quot;Shape&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;h2 class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun MacChromeBold SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;What you can do now&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Create a&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;Holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;group&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;in your&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Flags &amp;gt; Holdouts tab.&lt;/span&gt;&lt;/strong&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;&amp;nbsp;Set your holdout percentage,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;select what metrics to measure like Overall Revenue, what Audience,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;and&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;this holdout will get added to your next experimentation based on the criteria&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;. (I typically recomennd holding back between 1-5% of your traffic). Your next leadership review can include a number that answers the question that matters: what is our experimentation program delivering?&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&lt;img src=&quot;/link/298739ebb2c044bda8bfa985f1946583.aspx&quot; alt=&quot;&quot; width=&quot;781&quot; height=&quot;1460&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;For a full explanation of how holdout&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;s&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;work, see the&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW65388752 BCX0&quot; href=&quot;https://www.optimizely.com/optimization-glossary/holdout-groups/&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Holdouts Glossary Page&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Ready to get started?&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a class=&quot;Hyperlink SCXW65388752 BCX0&quot; href=&quot;https://app.optimizely.com/signin?_ga=2.147376567.1003395212.1673967086-1697401522.1672681705&amp;amp;_gl=1*1bfiiei*_gcl_aw*R0NMLjE3NzAxMzg3MzUuRUFJYUlRb2JDaE1JNzYzTTB1aTlrZ01WZ0NWRUNCM2U4UkNpRUFBWUFTQUFFZ0lYSGZEX0J3RQ..*_gcl_au*MTMwNDM3NzY1LjE3Njc2Mjk3NDIuMTI4MTQ0MjA0NC4xNzczMjQ1NjY5LjE3NzMyNDU2Njg.&quot;&gt;&lt;span class=&quot;TextRun Underlined SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;Log in to Optimizely Feature Experimentation&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;TextRun SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW65388752 BCX0&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;OutlineElement Ltr SCXW65388752 BCX0&quot;&gt;
&lt;p class=&quot;Paragraph SCXW65388752 BCX0&quot;&gt;&lt;span class=&quot;EOP SCXW65388752 BCX0&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;</description>            <guid>https://world.optimizely.com/blogs/sarahs-blog/dates/2026/3/holdouts-available-in-feature-experimentation/</guid>            <pubDate>Mon, 30 Mar 2026 16:15:32 GMT</pubDate>           <category>Blog post</category></item><item> <title>Supercharging Optimizely Forms: Introducing Dynamic Email Routing &amp; Conditional Submissions</title>            <link>https://world.optimizely.com/blogs/scott-reed/dates/2026/3/supercharging-optimizely-forms-introducing-dynamic-email-routing--conditional-submissions/</link>            <description>&lt;h1&gt;Supercharging Optimizely Forms: Introducing Dynamic Email Routing &amp;amp; Conditional Submissions&lt;/h1&gt;
&lt;p&gt;Optimizely Forms is a powerhouse for gathering user data, but as implementations grow in complexity, we often run into a common limitation with the built-in &quot;Send email after form submission&quot; actor: it&#39;s a bit static.&lt;/p&gt;
&lt;p&gt;In a typical enterprise scenario, you don&#39;t just want one email going to one place. You might need to route a lead to the &quot;Sales&quot; team if they select a specific department, or perhaps you only want an email sent if the user ticks a &quot;Request Callback&quot; box.&lt;/p&gt;
&lt;p&gt;To solve this, I&amp;rsquo;ve released an open-source package: &lt;strong&gt;ScottReed.Optimizely.Forms.DynamicEmailRouting&lt;/strong&gt;. It&amp;rsquo;s a custom post-submission actor for CMS 12 that brings dynamic routing and complex conditional logic directly into the Forms UI.&lt;/p&gt;
&lt;h2&gt;The Problem: The &quot;One-Size-Fits-All&quot; Email&lt;/h2&gt;
&lt;p&gt;The default email actor is great for simple notifications. However, once you need logic like &lt;em&gt;&quot;If Department is &#39;Support&#39;, send to support@company.com&quot;&lt;/em&gt; or &lt;em&gt;&quot;Only send this internal alert if &#39;Priority&#39; is &#39;Critical&#39;&quot;&lt;/em&gt;, you&#39;re usually forced to write custom code for every specific form or clutter the CMS with multiple overlapping actors.&lt;/p&gt;
&lt;h2&gt;The Solution: Dynamic Email Routing&lt;/h2&gt;
&lt;p&gt;This package extends the core functionality of the built-in email actor but adds two powerful layers: &lt;strong&gt;Email Routing&lt;/strong&gt; and &lt;strong&gt;Conditional Logic&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/link/c78d0dec2dd1401caeb7a445717a36e7.aspx&quot; width=&quot;1050&quot; height=&quot;272&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;1. Dynamic Email Routing&lt;/h3&gt;
&lt;p&gt;Instead of a single hardcoded &quot;To&quot; address, you can now define a mapping table. You select a form field, define a value to match, and specify the recipient. If no match is found, it gracefully falls back to the primary &quot;To&quot; address.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/link/f80e3f2362264b098a27fa060e82694f.aspx&quot; width=&quot;869&quot; height=&quot;133&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2. Conditional Logic (AND/OR)&lt;/h3&gt;
&lt;p&gt;Sometimes you don&#39;t want an email sent at all unless specific criteria are met. The actor allows you to add multiple conditions using &quot;is&quot; and &quot;is not&quot; operators. You can toggle between &quot;Match ALL&quot; (AND) or &quot;Match ANY&quot; (OR) logic.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/link/47e7253160a4452bb7a5f3c1042093c5.aspx&quot; width=&quot;869&quot; height=&quot;167&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Technical Implementation: Under the Hood&lt;/h2&gt;
&lt;p&gt;For the developers curious about how this is built, the package leverages several Optimizely extension points to ensure a &quot;native&quot; feel.&lt;/p&gt;
&lt;h3&gt;The Actor &amp;amp; Model&lt;/h3&gt;
&lt;p&gt;The core logic resides in &lt;code&gt;DynamicEmailRoutingActor&lt;/code&gt;, which inherits from &lt;code&gt;SendEmailAfterSubmissionActor&lt;/code&gt;. This is crucial because it allows us to reuse the existing &lt;code&gt;EmailTemplateActorModel&lt;/code&gt; features&amp;mdash;like the rich text editor, the &quot;Insert Placeholder&quot; dropdown, and the standard From/Subject fields&amp;mdash;without reinventing the wheel.&lt;/p&gt;
&lt;h3&gt;The UI (Dojo &amp;amp; Protected Modules)&lt;/h3&gt;
&lt;p&gt;To provide a seamless editor experience, the package uses the &lt;strong&gt;Protected Module pattern&lt;/strong&gt;. On build, the client-side resources (Dojo editors and language files) are zipped into a protected module folder.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve implemented three custom Dojo editors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;EmailRoutingEditor.js&lt;/code&gt;: Handles the dynamic table for routing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ConditionMatchEditor.js&lt;/code&gt;: A simple dropdown for logic selection.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ConditionsEditor.js&lt;/code&gt;: Manages the conditional rules.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Localization&lt;/h3&gt;
&lt;p&gt;All labels and the actor name are localized via XML files embedded within the module, ensuring it fits perfectly into the Optimizely UI language settings.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Installation is a standard NuGet affair. Because it uses an &lt;code&gt;IConfigurableModule&lt;/code&gt; for auto-registration, there&#39;s zero configuration required in your &lt;code&gt;Startup.cs&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Install via NuGet:&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://nuget.optimizely.com/packages/scottreed.optimizely.forms.dynamicemailrouting/&quot;&gt;https://nuget.optimizely.com/packages/scottreed.optimizely.forms.dynamicemailrouting/&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dotnet add package ScottReed.Optimizely.Forms.DynamicEmailRouting
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Configuration:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ensure your SMTP is configured in &lt;code&gt;appsettings.json&lt;/code&gt; (the actor uses the standard Optimizely SMTP client).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the CMS, add the &lt;strong&gt;Dynamic email routing&lt;/strong&gt; actor to your Form Container.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Define your routes and conditions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[Image Placeholder: Selecting the Dynamic Email Routing actor in the Form Settings tab]&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Extensibility&lt;/h2&gt;
&lt;p&gt;The project is built with extensibility in mind. If you need more complex operators (like &quot;contains&quot; or &quot;starts with&quot;), you can easily extend the &lt;code&gt;EvaluateConditions&lt;/code&gt; logic in the actor or contribute to the repository!&lt;/p&gt;
&lt;h2&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;By moving this logic into the CMS UI, we empower editors to manage complex workflows themselves without needing a deployment for every routing change.&lt;/p&gt;
&lt;p&gt;You can find the full source code, documentation, and a test Alloy site on GitHub: &#128073; &lt;a title=&quot;null&quot; href=&quot;https://github.com/scottreed/Optimizely-Dynamic-Form-Submission&quot;&gt;scottreed/Optimizely-Dynamic-Form-Submission&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d love to hear your feedback or see your PRs!&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/scott-reed/dates/2026/3/supercharging-optimizely-forms-introducing-dynamic-email-routing--conditional-submissions/</guid>            <pubDate>Mon, 30 Mar 2026 15:46:11 GMT</pubDate>           <category>Blog post</category></item><item> <title>How CMS Implementations Need to Change for GEO and AEO</title>            <link>https://www.technicaldogsbody.com/blog/cms-implementations-changes-for-geo-and-aeo</link>            <description>Search is changing. AI systems are increasingly the first point of contact between your content and your audience, and they don&#39;t behave like traditional search crawlers. If your CMS implementation was built purely with SEO in mind, it probably isn&#39;t ready for what&#39;s coming.</description>            <guid>https://www.technicaldogsbody.com/blog/cms-implementations-changes-for-geo-and-aeo</guid>            <pubDate>Fri, 27 Mar 2026 15:30:20 GMT</pubDate>           <category>Blog post</category></item><item> <title>VirtualText 2.0.0 beta for Optimizely CMS 13 previews</title>            <link>https://www.davidhome.net/blog/virtual-text-ready-v2-beta-for-cms-13-preview/</link>            <description>&lt;div&gt;&lt;div&gt;
&lt;div&gt;&lt;p&gt;&lt;code&gt;DavidHome.Optimizely.VirtualText&lt;/code&gt;&amp;nbsp;&lt;code&gt;2.0.0&lt;/code&gt; has been released as beta for Optimizely CMS 13 previews.&lt;/p&gt;
&lt;p&gt;This is a major technical release.&amp;nbsp;The focus is compatibility with CMS 13 previews,&amp;nbsp;updated routing behavior,&amp;nbsp;and alignment with Optimizely&#39;s newer application and shell APIs.&lt;/p&gt;
&lt;h2 id=&quot;what-changed&quot;&gt;What changed&lt;/h2&gt;
&lt;p&gt;VirtualText now relies more on Optimizely&#39;s application model and less on older site-definition-based assumptions.&amp;nbsp;Internally,&amp;nbsp;that means updated routing,&amp;nbsp;start page resolution,&amp;nbsp;and site context handling through APIs such as&amp;nbsp;&lt;code&gt;IApplicationRepository&lt;/code&gt;,&amp;nbsp;&lt;code&gt;IApplicationResolver&lt;/code&gt;,&amp;nbsp;and&amp;nbsp;&lt;code&gt;IRoutableApplication&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I also added&amp;nbsp;&lt;code&gt;ApplicationEventsSubscriber&lt;/code&gt;&amp;nbsp;so partial routers are registered from application lifecycle events,&amp;nbsp;and refactored several code paths from&amp;nbsp;&lt;code&gt;PageReference&lt;/code&gt;&amp;nbsp;to&amp;nbsp;&lt;code&gt;ContentReference&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On the UI side,&amp;nbsp;the plugin and RobotsTxt extension layouts were updated to use the newer Optimizely shell resources and components.&lt;/p&gt;
&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;2.0.0&lt;/code&gt;&amp;nbsp;beta is for CMS 13 previews only.&amp;nbsp;If your solution is on CMS 12,&amp;nbsp;stay on the previous VirtualText line.&lt;/p&gt;
&lt;p&gt;If you have custom code around&amp;nbsp;&lt;code&gt;SiteDefinition.Current&lt;/code&gt;,&amp;nbsp;&lt;code&gt;ISiteDefinitionRepository&lt;/code&gt;,&amp;nbsp;site-based routing assumptions,&amp;nbsp;or overridden plugin views,&amp;nbsp;review that code before upgrading.&lt;/p&gt;
&lt;p&gt;If you run a multi-site solution,&amp;nbsp;validate routing behavior explicitly after the upgrade.&amp;nbsp;Router registration now follows the application lifecycle.&lt;/p&gt;
&lt;p&gt;You should also expect small adjustments if your own code mirrors older&amp;nbsp;&lt;code&gt;PageReference&lt;/code&gt;-based assumptions.&lt;/p&gt;
&lt;h2 id=&quot;who-should-upgrade&quot;&gt;Who should upgrade&lt;/h2&gt;
&lt;p&gt;This beta is for teams already working with Optimizely CMS 13 previews and willing to validate a major-version upgrade.&lt;/p&gt;
&lt;p&gt;If that is your target,&amp;nbsp;this is the version to evaluate.&amp;nbsp;If not,&amp;nbsp;stay on the current stable line.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>            <guid>https://www.davidhome.net/blog/virtual-text-ready-v2-beta-for-cms-13-preview/</guid>            <pubDate>Fri, 27 Mar 2026 02:39:59 GMT</pubDate>           <category>Blog post</category></item><item> <title>Technical Q&amp;A for CMS 13</title>            <link>https://optimizely.blog/2026/03/technical-qa-for-cms-13/</link>            <description>This blog post explains what to expect when planning to upgrade to Optimizely CMS 13. It answers common technical questions about what’s involved in moving to CMS 13, what changes to expect, and where Optimizely is headed next.
</description>            <guid>https://optimizely.blog/2026/03/technical-qa-for-cms-13/</guid>            <pubDate>Thu, 26 Mar 2026 19:19:46 GMT</pubDate>           <category>Blog post</category></item><item> <title>Custom Property Editors in Optimizely CMS 13</title>            <link>https://world.optimizely.com/blogs/grzegorz-wiechec/dates/2026/3/custom-property-editors-in-optimizely-cms-13/</link>            <description>&lt;p&gt;When the world&amp;nbsp;&lt;a href=&quot;/link/5db655ef060049e2abdbf166e944c30c.aspx&quot;&gt;first saw how to create custom editors for Optimizely CMS&lt;/a&gt;&amp;nbsp;back in 2012,&amp;nbsp;it was a game-changer for Javascript developers.&amp;nbsp;For the first time,&amp;nbsp;we could build custom property editors that made content editors&#39;&amp;nbsp;lives easier and more productive.&lt;/p&gt;
&lt;p&gt;However, there was a catch: you needed to master the Dojo framework. Understanding define, declare,&amp;nbsp;mixins and dependecies wasn&#39;t exactly straightforward&amp;mdash;you had to become a&amp;nbsp;&lt;strong&gt;Dojo master&lt;/strong&gt;&amp;nbsp;to create even simple custom editors.&lt;/p&gt;
&lt;p&gt;Fast forward to today,&amp;nbsp;and&amp;nbsp;&lt;strong&gt;Optimizely CMS 13&lt;/strong&gt;&amp;nbsp;(&lt;a href=&quot;https://nuget.optimizely.com/packages/episerver.cms/13.0.0-preview4&quot;&gt;now available as preview&lt;/a&gt;)&amp;nbsp;still supports the Dojo approach&amp;nbsp;(for those who enjoy the classics),&amp;nbsp;but it also introduces a modern,&amp;nbsp;streamlined way to register editors as&amp;nbsp;&lt;strong&gt;ES6 modules&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This article will guide you through the new ES6 module approach.&lt;/p&gt;
&lt;h2&gt;Your First ES6 Module Editor&lt;/h2&gt;
&lt;p&gt;An editor in CMS 13 is simply a JavaScript function with the following signature:&lt;/p&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;export default function editorWithAllSettings(editorContainer, initialValue, onEditorValueChange, widgetSettings, readOnly)&lt;/code&gt;&lt;/pre&gt;
&lt;img class=&quot;code-fence-highlighter-copy-button-icon&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;&lt;strong&gt;Parameters&lt;/strong&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;editorContainer: The HTML element where your editor should be rendered&lt;/li&gt;
&lt;li&gt;initialValue: The initial value of the property&lt;/li&gt;
&lt;li&gt;onEditorValueChange: A callback function to notify the CMS when the value changes (triggers save to server)&lt;/li&gt;
&lt;li&gt;widgetSettings: Configuration passed from the server (optional)&lt;/li&gt;
&lt;li&gt;readonly: Boolean indicating whether the editor should be read-only&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The function can either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Return nothing (render directly into editorContainer)&lt;/li&gt;
&lt;li&gt;Return an object with lifecycle methods (render, updateValue, destroy)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Registering the Editor on the Server&lt;/h2&gt;
&lt;p&gt;After creating client editor JavaScript file, we need to register it on the server side. This part is similar to how you would register any custom editor, with one important addition: you need to set &lt;strong&gt;IsJavascriptModule = true&lt;/strong&gt;&amp;nbsp;to enable the new ES6 module registration.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[ContentType]
public class TestPage : PageData
{
    [ClientEditor(ClientEditingClass = &quot;ClientResources/Scripts/Editors/minimal-editor.js&quot;, IsJavascriptModule = true)]
    public virtual string SimpleProperty { get; set; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we can look closer at how to implement the editor.&lt;/p&gt;
&lt;h2&gt;The Simplest Editor: Direct Rendering&lt;/h2&gt;
&lt;p&gt;Let&#39;s start with the most basic example&amp;mdash;a function that renders a simple text input directly:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/9f5afc5aff574c04824d8060443f9e9c.aspx&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;export default function customEditor(editorContainer, initialValue, onEditorValueChange) {
    const input = document.createElement(&quot;input&quot;);
    input.type = &quot;text&quot;;
    input.value = initialValue || &quot;&quot;;
    input.onchange = (event) =&amp;gt; onEditorValueChange(event.target.value);
    editorContainer.appendChild(input);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are few key points to note about this approach is that no framework dependencies are required.&amp;nbsp;The only requirement is following the function signature convention.&lt;/p&gt;
&lt;p&gt;This approach works well for very simple scenarios,&amp;nbsp;such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read-only displays (e.g., links to external systems)&lt;/li&gt;
&lt;li&gt;Simple labels or informational fields&lt;/li&gt;
&lt;li&gt;Lightweight custom inputs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For scenarios requiring more interaction with the CMS&amp;nbsp;(like handling undo/redo),&amp;nbsp;it&#39;s recommended to return an object with lifecycle methods.&lt;/p&gt;
&lt;h2&gt;Returning an Object with Lifecycle Methods&lt;/h2&gt;
&lt;p&gt;Instead of rendering directly,&amp;nbsp;your function can return an object with predefined methods.&lt;/p&gt;
&lt;p&gt;The required is the &quot;render&quot;&amp;nbsp;method,&amp;nbsp;which is called to render the editor.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;export default function customEditor(editorContainer, initialValue, onEditorValueChange) {
    return {
        render: function () {
            const input = document.createElement(&quot;input&quot;);
            input.type = &quot;text&quot;;
            input.value = initialValue || &quot;&quot;;
            input.onchange = (event) =&amp;gt; onEditorValueChange(event.target.value);
            editorContainer.appendChild(input);
            this._input = input;
        },
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above example is functionally equivalent to the direct rendering approach.&amp;nbsp;However,&amp;nbsp;by returning an object,&amp;nbsp;you can also implement additional lifecycle methods for better integration with the CMS.&lt;/p&gt;
&lt;p&gt;Additional methods include &quot;updateValue&quot; and &quot;destroy&quot;:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;export default function editorWithAllSettings(editorContainer, initialValue, onEditorValueChange, widgetSettings, readOnly) {
    return {
        render: function () {
            console.log(&quot;rendering custom widget&quot;);

            const input = document.createElement(&quot;input&quot;);
            input.type = &quot;text&quot;;
            if (readOnly) {
                input.disabled = true;
            }
            input.value = initialValue || &quot;&quot;;
            input.onchange = (event) =&amp;gt; onEditorValueChange(event.target.value);
            editorContainer.appendChild(input);
            this._input = input;
        },
        updateValue: function (value) {
            console.log(&quot;updating custom widget value&quot;);
            this._input.value = value;
        },
        destroy: function () {
            console.log(&quot;removing custom widget&quot;);
        },
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Method purposes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;render(): Called to initially render the editor&lt;/li&gt;
&lt;li&gt;updateValue(): Called when the value needs to be updated (e.g., when using Undo/Redo functionality)&lt;/li&gt;
&lt;li&gt;destroy() :Called when the editor should be cleaned up (e.g., when navigating to a different page). Use this to remove event listeners and prevent memory leaks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Example: Text Area with Statistics&lt;/h2&gt;
&lt;p&gt;Now we can look closer at a more complex example that demonstrates the power of this approach.&amp;nbsp;Building on a&amp;nbsp;&lt;a href=&quot;/link/baba6bbe33874a5fbfd7f4bd7e37947c.aspx&quot;&gt;classic blog post by Ben McKernan&lt;/a&gt;, let&#39;s create a more sophisticated editor that displays live statistics, like character count, word count, and paragraph count about the text being entered:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/79419f58da8c48b69d5547916ef4001b.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;const count = (value) =&amp;gt; {
    const original = typeof value === &quot;string&quot; ? value : &quot;&quot;;
    const trimmed = original.trim();
    return {
        paragraphs: trimmed ? (trimmed.match(/\n+/g) || []).length + 1 : 0,
        words: trimmed ? (trimmed.replace(/[&#39;&quot;;:,.?&amp;iquest;\-!&amp;iexcl;]+/g, &quot;&quot;).match(/\S+/g) || []).length : 0,
        characters: trimmed ? trimmed.replace(/\s/g, &quot;&quot;).length : 0,
    };
};

export default function editorWithAllSettings(
    editorContainer,
    initialValue,
    onEditorValueChange,
    widgetSettings,
    readOnly
) {
    return {
        render: function () {
            const wrapper = document.createElement(&quot;div&quot;);
            wrapper.className = &quot;text-area-with-statistics&quot;;

            const textarea = document.createElement(&quot;textarea&quot;);
            if (readOnly) {
                textarea.disabled = true;
            }
            textarea.value = initialValue || &quot;&quot;;

            const stats = document.createElement(&quot;div&quot;);
            const updateStats = (value) =&amp;gt; {
                const { characters, words, paragraphs } = count(value);
                stats.textContent = `Characters: ${characters}\nWords: ${words}\nParagraphs: ${paragraphs}`;
            };
            stats.style.whiteSpace = &quot;pre&quot;;

            updateStats(textarea.value);

            textarea.oninput = (event) =&amp;gt; {
                onEditorValueChange(event.target.value);
                updateStats(event.target.value);
            };

            wrapper.appendChild(textarea);
            wrapper.appendChild(stats);
            editorContainer.appendChild(wrapper);

            this._textarea = textarea;
            this._stats = stats;
        },
        updateValue: function (value) {
            this._textarea.value = value;
            const { characters, words, paragraphs } = count(value);
            this._stats.textContent = `Characters: ${characters}\nWords: ${words}\nParagraphs: ${paragraphs}`;
        }
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This editor is around 50 lines of code, with no dependencies on any framework. It demonstrates how you can create a rich editing experience with live feedback using just vanilla JavaScript. The &quot;updateValue&quot; method ensures that the statistics are always in sync with the current value, even when changes come from outside the editor (e.g., Undo/Redo).&lt;/p&gt;
&lt;h2&gt;Passing Configuration from the Server&lt;/h2&gt;
&lt;p&gt;In many scenarios, we might want to pass custom settings from the server to your editor. For example we have dropdown editor and want to populate the options from the server, or we want to pass some initial text or configuration values. The best way to do this is by implementing a custom &quot;EditorDescriptor&quot;.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[EditorDescriptorRegistration(TargetType = typeof(string), UIHint = &quot;CustomModuleEditor&quot;)]
public class CustomEditorDescriptor : EditorDescriptor
{
    public CustomEditorDescriptor()
    {
        ClientEditingClass = &quot;ClientResources/Scripts/Editors/editor-with-custom-settings.js&quot;;
    }

    public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable&amp;lt;Attribute&amp;gt; attributes)
    {
        base.ModifyMetadata(metadata, attributes);

        metadata.EditorConfiguration[&quot;isJavascriptModule&quot;] = true;
        metadata.EditorConfiguration[&quot;initialTextFromServer&quot;] = &quot;Here is sample initial text from the server&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&amp;nbsp;Don&#39;t forget to set&amp;nbsp;&lt;code&gt;metadata.EditorConfiguration[&quot;isJavascriptModule&quot;] = true&lt;/code&gt;&amp;nbsp;to enable ES6 module mode.&lt;/p&gt;
&lt;p&gt;Then we can use this editor descriptor in our content type by specifying the &quot;CustomModuleEditor&quot; &lt;strong&gt;UIHint&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[ContentType]
public class TestPage : PageData
{
    [UIHint(&quot;CustomModuleEditor&quot;)]
    public virtual string EditorWithCustomSettings { get; set; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The server configuration is simply available through the &lt;strong&gt;widgetSettings&lt;/strong&gt;&amp;nbsp;object as field parameter:&lt;/p&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;&lt;img class=&quot;code-fence-highlighter-copy-button-icon&quot; /&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;export default function editorWithAllSettings(editorContainer, initialValue, onEditorValueChange, widgetSettings, readOnly) {
    return {
        render: function () {
            const wrapper = document.createElement(&quot;div&quot;);

            const input = document.createElement(&quot;input&quot;);
            input.type = &quot;text&quot;;
            if (readOnly) {
                input.disabled = true;
            }
            input.value = initialValue || &quot;&quot;;
            input.onchange = (event) =&amp;gt; onEditorValueChange(event.target.value);
            this._input = input;

            const descriptionEl = document.createElement(&quot;div&quot;);
            descriptionEl.textContent = widgetSettings.initialTextFromServer;

            wrapper.appendChild(input);
            wrapper.appendChild(descriptionEl);
            editorContainer.appendChild(wrapper);
        },
        updateValue: function (value) {
            this._input.value = value;
        }
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;/link/24491d2a0167452a9a997dc62da51027.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Advanced Scenarios: Modern Tooling and Frameworks&lt;/h2&gt;
&lt;p&gt;The real power of ES6 module registration goes beyond just simpler code.&amp;nbsp;You can now build custom editors using modern JavaScript tooling and development practices.&lt;/p&gt;
&lt;p&gt;The editor can be implemented outside of the CMS project,&amp;nbsp;with its own dependencies,&amp;nbsp;build process,&amp;nbsp;and development environment.&amp;nbsp;You can use React,&amp;nbsp;Vue,&amp;nbsp;Angular,&amp;nbsp;or any framework you prefer,&amp;nbsp;and bundle it with tools like Webpack or Vite.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&amp;nbsp;for type safety&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React&lt;/strong&gt;&amp;nbsp;for component composition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vite&lt;/strong&gt;&amp;nbsp;for fast builds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://optimizely-axiom.github.io/optiaxiom/&quot;&gt;Optimizely Axiom&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;for consistent UI components. Which give you same design system as Optimizely&#39;s own products, ensuring a polished, professional look and feel.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storybook&lt;/strong&gt;&amp;nbsp;for component development and documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vitest&lt;/strong&gt;&amp;nbsp;for unit testing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Example Project Structure for textarea with statistics editor&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;CustomEditorSample/
├── src/
│   ├── TextAreaWithStats.tsx          # React component
│   ├── TextAreaWithStats.stories.tsx  # Storybook stories
│   ├── count-statistics.ts            # Business logic
│   ├── count-statistics.test.ts       # Unit tests
│   └── index.ts                       # ES6 module wrapper
├── vite.config.js                      # Build configuration
└── package.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;The React Component&lt;/h3&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;&lt;img class=&quot;code-fence-highlighter-copy-button-icon&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &#39;react&#39;;
import { AxiomProvider, Textarea, Box, Group, Text } from &#39;@optiaxiom/react&#39;;

export const TextAreaWithStats: React.FC&amp;lt;TextAreaWithStatsProps&amp;gt; = ({
    initialValue = &#39;&#39;,
    onValueChange,
    readOnly = false,
}) =&amp;gt; {
    const [value, setValue] = useState&amp;lt;string&amp;gt;(initialValue);
    const [stats, setStats] = useState&amp;lt;TextStats&amp;gt;({ characters: 0, words: 0, paragraphs: 0 });

    useEffect(() =&amp;gt; {
        setStats(countStatistics(value));
    }, [value]);

    const handleChange = (e: React.ChangeEvent&amp;lt;HTMLTextAreaElement&amp;gt;) =&amp;gt; {
        const newValue = e.target.value;
        setValue(newValue);
        if (onValueChange) {
            onValueChange(newValue);
        }
    };

    return (
        &amp;lt;AxiomProvider&amp;gt;
            &amp;lt;Box&amp;gt;
                &amp;lt;Textarea
                    value={value}
                    onChange={handleChange}
                    disabled={readOnly}
                    placeholder=&quot;Enter text...&quot;
                /&amp;gt;
                &amp;lt;Group mt=&quot;4&quot; flexDirection=&quot;column&quot; gap=&quot;2&quot;&amp;gt;
                    &amp;lt;Text fontSize=&quot;md&quot; color=&quot;fg.secondary&quot;&amp;gt;
                        Characters: {stats.characters}
                    &amp;lt;/Text&amp;gt;
                    &amp;lt;Text fontSize=&quot;md&quot; color=&quot;fg.secondary&quot;&amp;gt;
                        Words: {stats.words}
                    &amp;lt;/Text&amp;gt;
                    &amp;lt;Text fontSize=&quot;md&quot; color=&quot;fg.secondary&quot;&amp;gt;
                        Paragraphs: {stats.paragraphs}
                    &amp;lt;/Text&amp;gt;
                &amp;lt;/Group&amp;gt;
            &amp;lt;/Box&amp;gt;
        &amp;lt;/AxiomProvider&amp;gt;
    );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &quot;index.ts&quot; file exports the editor function that the CMS expects, while using React internally:&lt;/p&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;&lt;img class=&quot;code-fence-highlighter-copy-button-icon&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;import React from &#39;react&#39;;
import { createRoot, Root } from &#39;react-dom/client&#39;;
import { TextAreaWithStats } from &#39;./TextAreaWithStats&#39;;

export default function editorWithAllSettings(
    editorContainer: HTMLElement,
    initialValue: string,
    onEditorValueChange: (value: string) =&amp;gt; void,
    widgetSettings?: Record&amp;lt;string, unknown&amp;gt;,
    readOnly?: boolean
) {
    let root: Root | null = null;

    return {
        render: function () {
            const container = document.createElement(&#39;div&#39;);
            editorContainer.appendChild(container);

            root = createRoot(container);
            root.render(
                React.createElement(TextAreaWithStats, {
                    initialValue,
                    onValueChange: onEditorValueChange,
                    readOnly,
                    widgetSettings,
                })
            );
        },
        updateValue: function (value: string) {
            if (root) {
                root.render(
                    React.createElement(TextAreaWithStats, {
                        initialValue: value,
                        onValueChange: onEditorValueChange,
                        readOnly,
                        widgetSettings,
                    })
                );
            }
        },
        destroy: function () {
            if (root) {
                root.unmount();
                root = null;
            }
        },
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Development with Storybook&lt;/h3&gt;
&lt;p&gt;Storybook allows you to develop and test your editor in isolation, without needing to run the full CMS.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/9bce104eeab84e2481743850c7df4637.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Unit Testing&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/link/4c42ee6a567a43f589a89f7b31df5e90.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Write tests for your business logic using Vitest:&lt;/p&gt;
&lt;div class=&quot;code-fence-highlighter-copy-button&quot;&gt;&lt;img class=&quot;code-fence-highlighter-copy-button-icon&quot; /&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;import { describe, expect, it } from &quot;vitest&quot;;
import { countStatistics } from &quot;./count-statistics&quot;;

describe(&quot;countStatistics&quot;, () =&amp;gt; {
    it(&quot;counts a single paragraph and strips punctuation from words&quot;, () =&amp;gt; {
        expect(countStatistics(&quot;  Hello, world!  &quot;)).toEqual({
            paragraphs: 1,
            words: 2,
            characters: 12,
        });
    });

    it(&quot;counts paragraph groups separated by newlines&quot;, () =&amp;gt; {
        expect(countStatistics(&quot;First line\nSecond line\n\nThird line&quot;)).toEqual({
            paragraphs: 3,
            words: 6,
            characters: 28,
        });
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/6691fd6bf9ef43f3a6ae3503d102b4a2.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The ES6 module approach gives you complete freedom to use vanilla JavaScript,&amp;nbsp;React,&amp;nbsp;Vue,&amp;nbsp;or any framework you prefer,&amp;nbsp;while taking advantage of modern development practices like TypeScript,&amp;nbsp;ESLint,&amp;nbsp;and Prettier.&amp;nbsp;You can write unit tests,&amp;nbsp;use Storybook for component development,&amp;nbsp;and benefit from hot module replacement and fast builds with Vite.&amp;nbsp;The code is cleaner,&amp;nbsp;more maintainable than Dojo-based editors,&amp;nbsp;and easily reusable across projects.&lt;/p&gt;
&lt;p&gt;The module approach in Optimizely CMS 13 is a step forward in custom editor development.&amp;nbsp;While the Dojo framework served us well for over a decade,&amp;nbsp;the new approach embraces modern JavaScript standards and development practices.&lt;/p&gt;
&lt;p&gt;Whether you&#39;re building a simple text input or a sophisticated React component with real-time validation,&amp;nbsp;the ES6 module registration makes it easier,&amp;nbsp;more maintainable,&amp;nbsp;and more enjoyable to create custom property editors.&lt;/p&gt;
&lt;p&gt;The best part?&amp;nbsp;You can adopt this gradually&amp;mdash;your existing Dojo editors will continue to work,&amp;nbsp;so you can migrate at your own pace.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>            <guid>https://world.optimizely.com/blogs/grzegorz-wiechec/dates/2026/3/custom-property-editors-in-optimizely-cms-13/</guid>            <pubDate>Thu, 26 Mar 2026 13:35:08 GMT</pubDate>           <category>Blog post</category></item><item> <title>Introducing the Optimizely CMS 13 Graph SDK</title>            <link>https://world.optimizely.com/blogs/jake-minard/dates/2026/3/introducing-optimizely-cms-13-graph-sdk/</link>            <description>&lt;p style=&quot;font-size: 1.2rem; color: #555; margin-bottom: 8px; font-weight: 400;&quot;&gt;Query Optimizely Graph Without Writing GraphQL. A C# fluent API that lets you migrate from Search &amp;amp; Navigation with familiar patterns.&lt;/p&gt;
&lt;div style=&quot;display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 32px;&quot;&gt;&lt;span style=&quot;background: #f0f4ff; color: #0037ff; font-size: 0.75rem; font-weight: 600; padding: 3px 10px; border-radius: 12px; display: inline-block;&quot;&gt;CMS 13&lt;/span&gt; &lt;span style=&quot;background: #f0f4ff; color: #0037ff; font-size: 0.75rem; font-weight: 600; padding: 3px 10px; border-radius: 12px; display: inline-block;&quot;&gt;Optimizely Graph&lt;/span&gt; &lt;span style=&quot;background: #f0f4ff; color: #0037ff; font-size: 0.75rem; font-weight: 600; padding: 3px 10px; border-radius: 12px; display: inline-block;&quot;&gt;Migration&lt;/span&gt; &lt;span style=&quot;background: #f0f4ff; color: #0037ff; font-size: 0.75rem; font-weight: 600; padding: 3px 10px; border-radius: 12px; display: inline-block;&quot;&gt;SDK&lt;/span&gt; &lt;span style=&quot;background: #f0f4ff; color: #0037ff; font-size: 0.75rem; font-weight: 600; padding: 3px 10px; border-radius: 12px; display: inline-block;&quot;&gt;Search &amp;amp; Navigation&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;background: linear-gradient(135deg,#f0f4ff 0%,#e8f0fe 100%); border: 1px solid #93c5fd; border-left: 4px solid #2563eb; border-radius: 8px; padding: 10px 28px; margin: 0 0 40px;&quot;&gt;
&lt;h3 style=&quot;margin-top: 0;&quot;&gt;TL;DR&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Search &amp;amp; Navigation is gone in CMS 13.&lt;/strong&gt; Optimizely Graph is the replacement, and the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Optimizely.Graph.Cms.Query&lt;/span&gt;&lt;/strong&gt; SDK lets you query it with familiar C# fluent patterns instead of raw GraphQL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The API mirrors what you know:&lt;/strong&gt; &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Filter()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SearchFor()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;For()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Limit()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Take()&lt;/span&gt;&lt;/strong&gt;. Your muscle memory transfers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Three entry points:&lt;/strong&gt; &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;QueryContent&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; for CMS content, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; for any type, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query(&quot;TypeName&quot;)&lt;/span&gt;&lt;/strong&gt; for dynamic scenarios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New capabilities included:&lt;/strong&gt; Boolean facets, IAsyncEnumerable streaming, decay/factor scoring, pinned results, named queries, and cursor-based pagination.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt; is your best friend.&lt;/strong&gt; Call it on any query to inspect the generated GraphQL. This will be invaluable during migration.&lt;/li&gt;
&lt;li&gt;A complete migration reference table (Section 12) maps every Search &amp;amp; Navigation API to its Graph SDK equivalent.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;1. Why This SDK Exists&lt;/h2&gt;
&lt;p&gt;With CMS 13, Optimizely is replacing Search &amp;amp; Navigation (formerly Episerver Find) with &lt;strong&gt;Optimizely Graph&lt;/strong&gt; as the platform&#39;s content query engine. This is not an optional migration, Search &amp;amp; Navigation will not be available in CMS 13.&lt;/p&gt;
&lt;p&gt;For many partner developers, this triggers understandable anxiety. Search &amp;amp; Navigation&#39;s fluent API has been the go-to for content querying for years. Teams have accumulated deep expertise in its fluent &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Search&amp;lt;T&amp;gt;().For().Filter()&lt;/span&gt;&lt;/strong&gt; patterns, and the prospect of learning GraphQL from scratch feels like a significant lift on top of everything else in a CMS 13 migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That&#39;s exactly why the Graph SDK exists.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Optimizely.Graph.Cms.Query&lt;/span&gt;&lt;/strong&gt; package provides a C# fluent API that compiles your familiar expressions into GraphQL queries behind the scenes. You write C#. The SDK writes GraphQL. Optimizely Graph executes it.&lt;/p&gt;
&lt;div style=&quot;border-left: 4px solid #2563eb; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dbeafe;&quot;&gt;&lt;strong&gt;You do not need to learn GraphQL to use Optimizely Graph.&lt;/strong&gt;
&lt;p&gt;The SDK translates your C# lambda expressions into optimized GraphQL queries automatically. If you&#39;ve used Search &amp;amp; Navigation, you already know 90% of what you need.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The API intentionally mirrors Search &amp;amp; Navigation patterns where possible: &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Filter()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SearchFor()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;For()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Limit()&lt;/span&gt;&lt;/strong&gt; replaces &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Take()&lt;/span&gt;&lt;/strong&gt;. The muscle memory transfers.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;2. Getting Started&lt;/h2&gt;
&lt;h3&gt;DI Registration&lt;/h3&gt;
&lt;p&gt;Register the Graph content client in your &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Startup.cs&lt;/span&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Program.cs&lt;/span&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Program.cs or Startup.cs&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #004d40;&quot;&gt;services&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;AddGraphContentClient&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Inject the Client&lt;/h3&gt;
&lt;p&gt;Inject &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IGraphContentClient&lt;/span&gt;&lt;/strong&gt; into your controllers, services, or view components:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;public class&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;SearchController&lt;/span&gt; : &lt;span style=&quot;color: #004d40;&quot;&gt;Controller&lt;/span&gt;
{
    &lt;span style=&quot;color: #000080;&quot;&gt;private readonly&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;IGraphContentClient&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;;

    &lt;span style=&quot;color: #000080;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000cc;&quot;&gt;SearchController&lt;/span&gt;(&lt;span style=&quot;color: #004d40;&quot;&gt;IGraphContentClient&lt;/span&gt; graphClient)
    {
        &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt; = graphClient;
    }
}&lt;/pre&gt;
&lt;h3&gt;Three Entry Points&lt;/h3&gt;
&lt;p&gt;The SDK provides three ways to start a query, depending on your needs:&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 0.9rem;&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Method&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Use Case&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Type Constraint&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;QueryContent&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Strongly-typed CMS content queries&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;T : class, IContentData&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ISearchableContentQuery&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Strongly-typed queries for any class&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;T : class&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ISearchableQuery&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query(&quot;TypeName&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Untyped queries by content type name&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;None&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ISearchableQuery&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;QueryContent&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; is the most common choice for CMS content. It constrains &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;T&lt;/span&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentData&lt;/span&gt;&lt;/strong&gt;, giving you access to CMS-specific features like content resolution via &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsContentAsync()&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; works with any class, not just CMS content types. Use this when querying custom types indexed in Graph that don&#39;t implement &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentData&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query(&quot;TypeName&quot;)&lt;/span&gt;&lt;/strong&gt; creates an untyped query using a string type name. Useful for dynamic scenarios where the content type isn&#39;t known at compile time.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;3. Your First Query&lt;/h2&gt;
&lt;p&gt;Let&#39;s see the same query expressed three ways. &lt;strong&gt;Goal:&lt;/strong&gt; Find all recipes in the &quot;Dessert&quot; category, returning only Name and Description.&lt;/p&gt;
&lt;div style=&quot;margin: 16px 0;&quot;&gt;
&lt;div style=&quot;font-size: 0.75rem; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; padding: 6px 14px; border-radius: 8px 8px 0 0; color: #fff; background: #ef4444;&quot;&gt;Before - Search &amp;amp; Navigation&lt;/div&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 0 0 8px 8px; padding: 16px 20px; overflow-x: auto; margin: 0 0 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = searchClient.&lt;span style=&quot;color: #0000cc;&quot;&gt;Search&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Filter&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Select&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; { x.Name, x.Description })
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetResult&lt;/span&gt;();&lt;/pre&gt;
&lt;div style=&quot;font-size: 0.75rem; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; padding: 6px 14px; border-radius: 8px 8px 0 0; color: #fff; background: #16a34a;&quot;&gt;After - Graph SDK&lt;/div&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 0 0 8px 8px; padding: 16px 20px; overflow-x: auto; margin: 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: #000080;&quot;&gt;nameof&lt;/span&gt;(&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;.Name), &lt;span style=&quot;color: #000080;&quot;&gt;nameof&lt;/span&gt;(&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;.Description))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The parallels are clear: &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Filter()&lt;/span&gt;&lt;/strong&gt; becomes &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Select()&lt;/span&gt;&lt;/strong&gt; becomes &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Fields&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetResult()&lt;/span&gt;&lt;/strong&gt; becomes &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsync()&lt;/span&gt;&lt;/strong&gt;. The Graph SDK is async-first, returning &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Task&amp;lt;IContentResult&amp;lt;T&amp;gt;&amp;gt;&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;GetAsContentAsync() - CMS Content Resolution&lt;/h3&gt;
&lt;p&gt;When querying CMS content types, use &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsContentAsync()&lt;/span&gt;&lt;/strong&gt; to resolve results directly as &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContent&lt;/span&gt;&lt;/strong&gt; items. This returns the same fully-resolved content objects that Search &amp;amp; Navigation&#39;s &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetResult()&lt;/span&gt;&lt;/strong&gt; provided.&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsContentAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// result implements IEnumerable&amp;lt;IContent&amp;gt;&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;foreach&lt;/span&gt; (&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; content &lt;span style=&quot;color: #000080;&quot;&gt;in&lt;/span&gt; result)
{
    &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// content is IContent, fully resolved from CMS&lt;/em&gt;&lt;/span&gt;
}&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #f59e0b; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #fef3c7;&quot;&gt;&lt;strong&gt;Do not use .Fields() with GetAsContentAsync()&lt;/strong&gt;
&lt;p&gt;The SDK generates a minimal query fetching only content identifiers (&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;_id&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;_metadata&lt;/span&gt;&lt;/strong&gt;), then resolves full &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContent&lt;/span&gt;&lt;/strong&gt; objects through the CMS content loader. Calling &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Fields()&lt;/span&gt;&lt;/strong&gt; with an &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentData&lt;/span&gt;&lt;/strong&gt; projection type will throw &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;InvalidOperationException&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Generated GraphQL&lt;/h3&gt;
&lt;p&gt;For the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsync()&lt;/span&gt;&lt;/strong&gt; query above (with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Fields&lt;/span&gt;&lt;/strong&gt;), the SDK generates:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;{
  &lt;span style=&quot;color: #0000cc;&quot;&gt;Recipe&lt;/span&gt;(&lt;span style=&quot;color: #660033;&quot;&gt;where&lt;/span&gt;: { &lt;span style=&quot;color: #0000cc;&quot;&gt;category&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;eq&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt; } }) {
    &lt;span style=&quot;color: #0000cc;&quot;&gt;items&lt;/span&gt; {
      &lt;span style=&quot;color: #0000cc;&quot;&gt;Name&lt;/span&gt;
      &lt;span style=&quot;color: #0000cc;&quot;&gt;Description&lt;/span&gt;
    }
  }
}&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #16a34a; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dcfce7;&quot;&gt;&lt;strong&gt;Tip: Use &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt;&lt;/strong&gt;
&lt;p&gt;Call &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt; on any query to see the generated GraphQL without executing it. This is invaluable for debugging and learning how your C# maps to GraphQL.&lt;/p&gt;
&lt;/div&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt; graphql = &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;ToGraphQL&lt;/span&gt;();

&lt;span style=&quot;color: #004d40;&quot;&gt;Console&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;WriteLine&lt;/span&gt;(graphql);&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsync()&lt;/span&gt;&lt;/strong&gt; returns raw Graph results as &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentResult&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;. Use with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Fields&amp;lt;TProjection&amp;gt;()&lt;/span&gt;&lt;/strong&gt; to specify which fields to return.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsContentAsync()&lt;/span&gt;&lt;/strong&gt; resolves results through the CMS content loader, returning &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IGetAsContentResult&amp;lt;IContent&amp;gt;&lt;/span&gt;&lt;/strong&gt;. Do not use &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Fields()&lt;/span&gt;&lt;/strong&gt; with this method.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsContentAsync()&lt;/span&gt;&lt;/strong&gt; is only available on &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;QueryContent&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; queries.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;4. Filtering&lt;/h2&gt;
&lt;p&gt;Filtering is where you&#39;ll spend most of your time. The SDK provides multiple approaches, from simple lambda expressions to a dynamic &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;FilterBuilder&lt;/span&gt;&lt;/strong&gt; API.&lt;/p&gt;
&lt;h3&gt;Lambda Expressions&lt;/h3&gt;
&lt;p&gt;The most natural way to filter, standard C# comparison operators inside a&amp;nbsp;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where()&lt;/span&gt;&lt;/strong&gt; lambda:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Equality&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Not equal&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;!=&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Archived&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Numeric comparisons&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Rating &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;4&lt;/span&gt;)
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.CookingTime &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;30&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Boolean&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.IsPublished)
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; !x.IsArchived)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Compound conditions with &amp;amp;&amp;amp; and ||&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt; &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x.Rating &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;4&lt;/span&gt; &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x.IsPublished)
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Appetizer&quot;&lt;/span&gt; &lt;span style=&quot;color: #6b3a00;&quot;&gt;||&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Full example with compound conditions:&lt;/strong&gt;&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Cookies&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt; &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x.Rating &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;4&lt;/span&gt; &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x.IsPublished)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Name, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Description)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Generated GraphQL:&lt;/strong&gt;&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;{
  &lt;span style=&quot;color: #0000cc;&quot;&gt;Recipe&lt;/span&gt;(
    &lt;span style=&quot;color: #660033;&quot;&gt;where&lt;/span&gt;: {
      &lt;span style=&quot;color: #0000cc;&quot;&gt;_and&lt;/span&gt;: [
        { &lt;span style=&quot;color: #0000cc;&quot;&gt;category&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;eq&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt; } }
        { &lt;span style=&quot;color: #0000cc;&quot;&gt;rating&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;gt&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;4&lt;/span&gt; } }
        { &lt;span style=&quot;color: #0000cc;&quot;&gt;isPublished&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;eq&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;true&lt;/span&gt; } }
      ]
      &lt;span style=&quot;color: #0000cc;&quot;&gt;_fulltext&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;match&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Cookies&quot;&lt;/span&gt; }
    }
  ) {
    &lt;span style=&quot;color: #0000cc;&quot;&gt;items&lt;/span&gt; { &lt;span style=&quot;color: #0000cc;&quot;&gt;Name&lt;/span&gt;  &lt;span style=&quot;color: #0000cc;&quot;&gt;Description&lt;/span&gt; }
  }
}&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #2563eb; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dbeafe;&quot;&gt;&lt;strong&gt;Multiple .Where() calls&lt;/strong&gt;
&lt;p&gt;You can chain multiple &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where()&lt;/span&gt;&lt;/strong&gt; calls on the same query. Each call adds an AND condition.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;String Filters&lt;/h3&gt;
&lt;p&gt;Extension methods for string operations that go beyond what lambda expressions can express:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Exact match&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Jane Doe&quot;&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Like -- SQL-style wildcards (% = 0+ chars, _ = single char)&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title.&lt;span style=&quot;color: #0000cc;&quot;&gt;Like&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%chocolate%&quot;&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Contains -- substring search&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title.&lt;span style=&quot;color: #0000cc;&quot;&gt;Contains&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate&quot;&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// StartsWith&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title.&lt;span style=&quot;color: #0000cc;&quot;&gt;StartsWith&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;How to&quot;&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// In -- matches any value in a collection&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;In&lt;/span&gt;(&lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt;[] { &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Appetizer&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Main Course&quot;&lt;/span&gt; }))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Exists -- check if field has/lacks a value&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author.&lt;span style=&quot;color: #0000cc;&quot;&gt;Exists&lt;/span&gt;())       &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// has a value&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author.&lt;span style=&quot;color: #0000cc;&quot;&gt;Exists&lt;/span&gt;(&lt;span style=&quot;color: #000080;&quot;&gt;false&lt;/span&gt;))  &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// is null&lt;/em&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h3&gt;Collection and Range Filters&lt;/h3&gt;
&lt;p&gt;Numeric and DateTime properties support range-based filtering:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Numeric range (inclusive)&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.CookingTime.&lt;span style=&quot;color: #0000cc;&quot;&gt;InRange&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;15&lt;/span&gt;, &lt;span style=&quot;color: #800000;&quot;&gt;45&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Greater than / Less than&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Rating.&lt;span style=&quot;color: #0000cc;&quot;&gt;GreaterThan&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;3&lt;/span&gt;))
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.CookingTime.&lt;span style=&quot;color: #0000cc;&quot;&gt;LessThanOrEqual&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;60&lt;/span&gt;))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// DateTime range&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate.&lt;span style=&quot;color: #0000cc;&quot;&gt;InRange&lt;/span&gt;(startDate, endDate))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// DateTime comparisons&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate.&lt;span style=&quot;color: #0000cc;&quot;&gt;GreaterThan&lt;/span&gt;(&lt;span style=&quot;color: #004d40;&quot;&gt;DateTime&lt;/span&gt;.UtcNow.&lt;span style=&quot;color: #0000cc;&quot;&gt;AddDays&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;-30&lt;/span&gt;)))&lt;/pre&gt;
&lt;h3&gt;Dynamic FilterBuilder API&lt;/h3&gt;
&lt;p&gt;For scenarios where filters must be built at runtime. Based on user input, iterating over collections, or applying conditional logic:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; filter = &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;BuildFilter&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;();

&lt;span style=&quot;color: #000080;&quot;&gt;if&lt;/span&gt; (!&lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;IsNullOrEmpty&lt;/span&gt;(selectedCategory))
{
    filter = filter.&lt;span style=&quot;color: #0000cc;&quot;&gt;And&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(selectedCategory));
}

&lt;span style=&quot;color: #000080;&quot;&gt;if&lt;/span&gt; (minRating.HasValue)
{
    filter = filter.&lt;span style=&quot;color: #0000cc;&quot;&gt;And&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Rating.&lt;span style=&quot;color: #0000cc;&quot;&gt;GreaterThanOrEqual&lt;/span&gt;(minRating.Value));
}

&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Filter&lt;/span&gt;(filter)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Name, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Description)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Combining with OR logic:&lt;/strong&gt;&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; filter = &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;BuildFilter&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Or&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Or&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Appetizer&quot;&lt;/span&gt;))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Or&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Snack&quot;&lt;/span&gt;));&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #2563eb; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dbeafe;&quot;&gt;&lt;strong&gt;Key FilterBuilder Details&lt;/strong&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;BuildFilter&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; is an extension method on &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IGraphContentClient&lt;/span&gt;&lt;/strong&gt;. Each &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.And()&lt;/span&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Or()&lt;/span&gt;&lt;/strong&gt; call returns a &lt;strong&gt;new&lt;/strong&gt; &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;FilterBuilder&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt; instance (immutable). &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;FilterBuilder&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt; has an implicit conversion to &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GraphFilter&lt;/span&gt;&lt;/strong&gt;, so it can also be passed to &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(GraphFilter)&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Combining Where() and Filter()&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; dynamicFilter = &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;BuildFilter&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;And&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.IsPublished.&lt;span style=&quot;color: #0000cc;&quot;&gt;Match&lt;/span&gt;(&lt;span style=&quot;color: #000080;&quot;&gt;true&lt;/span&gt;))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;And&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Rating.&lt;span style=&quot;color: #0000cc;&quot;&gt;GreaterThan&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;3&lt;/span&gt;));

&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)  &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Lambda expression&lt;/em&gt;&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Filter&lt;/span&gt;(dynamicFilter)                  &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// FilterBuilder&lt;/em&gt;&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Name, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Description)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #f59e0b; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #fef3c7;&quot;&gt;&lt;strong&gt;Where() vs Filter()&lt;/strong&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where()&lt;/span&gt;&lt;/strong&gt; adds filter conditions directly. &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Filter()&lt;/span&gt;&lt;/strong&gt; accepts a &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;FilterBuilder&amp;lt;T&amp;gt;?&lt;/span&gt;&lt;/strong&gt; specifically, which is designed for the dynamic filter-building pattern. Both can be combined in the same query.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;font-size: 0.88rem; color: #666; font-style: italic; margin-top: 16px;&quot;&gt;See the complete migration reference (Section 12) for S&amp;amp;N filter equivalents.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;5. Full-Text Search&lt;/h2&gt;
&lt;p&gt;Full-text search follows a chain pattern: &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SearchFor()&lt;/span&gt;&lt;/strong&gt; opens the search context, then &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;UsingFullText()&lt;/span&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;UsingField()&lt;/span&gt;&lt;/strong&gt; configure how the search is applied.&lt;/p&gt;
&lt;h3&gt;Basic Full-Text Search&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate cake recipe&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SearchFor()&lt;/span&gt;&lt;/strong&gt; returns &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ISearchFieldContentQuery&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;, which adds three search-specific methods: &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;UsingFullText()&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;UsingField()&lt;/span&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Track()&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;UsingFullText&lt;/h3&gt;
&lt;p&gt;Apply the search term across all searchable fields with optional highlighting and boost:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate cake&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingFullText&lt;/span&gt;(highlightTag: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;&amp;lt;mark&amp;gt;&quot;&lt;/span&gt;, boost: &lt;span style=&quot;color: #800000;&quot;&gt;2&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;UsingField - Targeted Search with Boost&lt;/h3&gt;
&lt;p&gt;Target the search to specific fields with per-field boost values:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate cake&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingField&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, boost: &lt;span style=&quot;color: #800000;&quot;&gt;3&lt;/span&gt;, highlightTag: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;&amp;lt;strong&amp;gt;&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingField&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary, boost: &lt;span style=&quot;color: #800000;&quot;&gt;2&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingField&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Body, boost: &lt;span style=&quot;color: #800000;&quot;&gt;1&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p style=&quot;font-size: 0.88rem; color: #666; font-style: italic; margin-top: 16px;&quot;&gt;See the complete migration reference (Section 12) for S&amp;amp;N search equivalents.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;6. Faceted Search&lt;/h2&gt;
&lt;p&gt;Facets aggregate your results into buckets (categories, date ranges, numeric ranges, or boolean groups). The SDK provides separate &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Facet()&lt;/span&gt;&lt;/strong&gt; overloads for each data type.&lt;/p&gt;
&lt;h3&gt;String Facets&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// With ordering and limits&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category,
       limit: &lt;span style=&quot;color: #800000;&quot;&gt;10&lt;/span&gt;,
       orderType: &lt;span style=&quot;color: #004d40;&quot;&gt;OrderType&lt;/span&gt;.COUNT,
       direction: &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)&lt;/pre&gt;
&lt;h3&gt;Range Facets (int)&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.CookingTime, ranges: &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt;[]
    {
        &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;RangeFacetInput&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;int&lt;/span&gt;&amp;gt; { From = &lt;span style=&quot;color: #800000;&quot;&gt;0&lt;/span&gt;, To = &lt;span style=&quot;color: #800000;&quot;&gt;15&lt;/span&gt; },
        &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;RangeFacetInput&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;int&lt;/span&gt;&amp;gt; { From = &lt;span style=&quot;color: #800000;&quot;&gt;15&lt;/span&gt;, To = &lt;span style=&quot;color: #800000;&quot;&gt;30&lt;/span&gt; },
        &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;RangeFacetInput&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;int&lt;/span&gt;&amp;gt; { From = &lt;span style=&quot;color: #800000;&quot;&gt;30&lt;/span&gt;, To = &lt;span style=&quot;color: #800000;&quot;&gt;60&lt;/span&gt; },
        &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;RangeFacetInput&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;int&lt;/span&gt;&amp;gt; { From = &lt;span style=&quot;color: #800000;&quot;&gt;60&lt;/span&gt;, To = &lt;span style=&quot;color: #800000;&quot;&gt;120&lt;/span&gt; }
    })
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Name, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.CookingTime)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Boolean Facets &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Boolean facets are &lt;strong&gt;new in the Graph SDK&lt;/strong&gt; (Search &amp;amp; Navigation did not support them):&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.IsFeatured)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.IsFeatured)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Facet Filtering: OR Within, AND Between&lt;/h3&gt;
&lt;p&gt;The Graph SDK applies facet filters with intuitive boolean logic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Within a single facet:&lt;/strong&gt; values are combined with &lt;strong&gt;OR&lt;/strong&gt;. Selecting &quot;Dessert&quot; and &quot;Appetizer&quot; in Category returns items in Dessert &lt;em&gt;or&lt;/em&gt; Appetizer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Between different facets:&lt;/strong&gt; filters are combined with &lt;strong&gt;AND&lt;/strong&gt;. Selecting &quot;Dessert&quot; in Category &lt;em&gt;and&lt;/em&gt; &quot;Jane Doe&quot; in Author returns items matching both.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category, filters: &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt;[] { &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Appetizer&quot;&lt;/span&gt; })  &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// OR&lt;/em&gt;&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author, filters: &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt;[] { &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Jane Doe&quot;&lt;/span&gt; })              &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// AND with above&lt;/em&gt;&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsContentAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Returns: (Category is Dessert OR Appetizer) AND (Author is Jane Doe)&lt;/em&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #16a34a; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dcfce7;&quot;&gt;&lt;strong&gt;Improvement over S&amp;amp;N&lt;/strong&gt;
&lt;p&gt;In Search &amp;amp; Navigation, achieving OR-within / AND-between facets required executing multiple search queries and merging results. With the Graph SDK, a single query handles it natively.&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Reading Facet Results&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Facet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Read facet values (type-safe)&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; authorFacets = result.Facets.&lt;span style=&quot;color: #0000cc;&quot;&gt;GetFacet&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author);

&lt;span style=&quot;color: #000080;&quot;&gt;foreach&lt;/span&gt; (&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; facet &lt;span style=&quot;color: #000080;&quot;&gt;in&lt;/span&gt; authorFacets)
{
    &lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt; name = facet.Name;   &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// e.g., &quot;Jane Doe&quot;&lt;/em&gt;&lt;/span&gt;
    &lt;span style=&quot;color: #000080;&quot;&gt;int&lt;/span&gt; count = facet.Count;    &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// e.g., 15&lt;/em&gt;&lt;/span&gt;
}

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Other helpers&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;bool&lt;/span&gt; hasFacet = result.Facets.&lt;span style=&quot;color: #0000cc;&quot;&gt;HasFacet&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Author&quot;&lt;/span&gt;);
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; fieldNames = result.Facets.FieldNames; &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// [&quot;Author&quot;, &quot;Category&quot;]&lt;/em&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p style=&quot;font-size: 0.88rem; color: #666; font-style: italic; margin-top: 16px;&quot;&gt;See the complete migration reference (Section 12) for S&amp;amp;N facet equivalents.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;7. Sorting, Pagination &amp;amp; Streaming&lt;/h2&gt;
&lt;h3&gt;Sorting&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Sort by property (descending)&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;OrderBy()&lt;/span&gt;&lt;/strong&gt; returns &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IOrderedContentQuery&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;, which allows chaining additional sort criteria with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ThenBy()&lt;/span&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Primary sort by date, secondary sort by title&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
.&lt;span style=&quot;color: #0000cc;&quot;&gt;ThenBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Ascending)&lt;/pre&gt;
&lt;h3&gt;Ranking &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;When using full-text search, sort by relevance score using the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;_ranking&lt;/span&gt;&lt;/strong&gt; pseudo-field with a &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;RankingMode&lt;/span&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingFullText&lt;/span&gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;UsingField&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, boost: &lt;span style=&quot;color: #800000;&quot;&gt;10&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;_ranking&quot;&lt;/span&gt;, &lt;span style=&quot;color: #004d40;&quot;&gt;RankingMode&lt;/span&gt;.Relevance)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;ThenBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Limit&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;15&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsContentAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Pagination&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Skip and Limit&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Skip&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;20&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Limit&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;10&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;IncludeTotal&lt;/span&gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();

&lt;span style=&quot;color: #000080;&quot;&gt;int&lt;/span&gt; totalCount = result.Total; &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// populated when IncludeTotal() is used&lt;/em&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h3&gt;IAsyncEnumerable Streaming &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;For large result sets, stream results page-by-page without loading everything into memory:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;await foreach&lt;/span&gt; (&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; page &lt;span style=&quot;color: #000080;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsyncEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;(pageSize: &lt;span style=&quot;color: #800000;&quot;&gt;50&lt;/span&gt;))
{
    &lt;span style=&quot;color: #000080;&quot;&gt;foreach&lt;/span&gt; (&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; item &lt;span style=&quot;color: #000080;&quot;&gt;in&lt;/span&gt; page.Items)
    {
        &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Process each item&lt;/em&gt;&lt;/span&gt;
    }
}&lt;/pre&gt;
&lt;p style=&quot;font-size: 0.88rem; color: #666; font-style: italic; margin-top: 16px;&quot;&gt;See the complete migration reference (Section 12) for S&amp;amp;N sorting/pagination equivalents.&lt;/p&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;8. Projections, Autocomplete &amp;amp; Locale&lt;/h2&gt;
&lt;h3&gt;Field Projection&lt;/h3&gt;
&lt;p&gt;Control which fields are returned to reduce payload size and improve performance:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Lambda-based (type-safe)&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;Recipe&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Name, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Description)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;p&gt;You can project to any class that has matching properties, as long as it does not implement &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentData&lt;/span&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;public class&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;RecipeResult&lt;/span&gt;
{
    &lt;span style=&quot;color: #000080;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt; Name { &lt;span style=&quot;color: #000080;&quot;&gt;get&lt;/span&gt;; &lt;span style=&quot;color: #000080;&quot;&gt;set&lt;/span&gt;; }
    &lt;span style=&quot;color: #000080;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt; Description { &lt;span style=&quot;color: #000080;&quot;&gt;get&lt;/span&gt;; &lt;span style=&quot;color: #000080;&quot;&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;h3&gt;Autocomplete&lt;/h3&gt;
&lt;p&gt;Provide type-ahead suggestions based on indexed field values:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Autocomplete&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;choc&quot;&lt;/span&gt;, limit: &lt;span style=&quot;color: #800000;&quot;&gt;5&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Locale and Multi-Language&lt;/h3&gt;
&lt;p&gt;Control which language versions of content are returned:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Single locale&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetLocale&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;en&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Multiple locales&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetLocale&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;en&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// All locales&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetLocale&lt;/span&gt;(&lt;span style=&quot;color: #004d40;&quot;&gt;QueryLocale&lt;/span&gt;.All)&lt;/pre&gt;
&lt;p&gt;If &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SetLocale()&lt;/span&gt;&lt;/strong&gt; is not called, the SDK uses the default locale for the current thread.&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SetLocale&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;en&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;9. Content Variations, Auth &amp;amp; Caching&lt;/h2&gt;
&lt;h3&gt;Content Variations &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Content Variations are a new concept in Optimizely Graph. Content Variations support scenarios like A/B testing and personalization where the same content exists in multiple variations.&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Include a specific variation plus the original content&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetVariation&lt;/span&gt;(includeOriginal: &lt;span style=&quot;color: #000080;&quot;&gt;true&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;WinterCampaign&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Include only the specific variation (exclude original)&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetVariation&lt;/span&gt;(includeOriginal: &lt;span style=&quot;color: #000080;&quot;&gt;false&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;WinterCampaign&quot;&lt;/span&gt;)

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Include all variations via options builder&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;SetVariation&lt;/span&gt;(options &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt;
{
    options.Include = &lt;span style=&quot;color: #004d40;&quot;&gt;VariationScope&lt;/span&gt;.All;
    options.IncludeOriginal = &lt;span style=&quot;color: #000080;&quot;&gt;true&lt;/span&gt;;
})&lt;/pre&gt;
&lt;h3&gt;WithDisplayFilters() - Context-Aware Access (Recommended)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;WithDisplayFilters()&lt;/span&gt;&lt;/strong&gt; is the recommended approach for page rendering scenarios. It automatically detects the current user from &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Thread.CurrentPrincipal&lt;/span&gt;&lt;/strong&gt; and adjusts authentication accordingly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No authenticated user:&lt;/strong&gt; Uses SingleKey mode (public content only)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authenticated user detected:&lt;/strong&gt; Switches to BasicAuth with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;AsUser()&lt;/span&gt;&lt;/strong&gt;, making user-restricted content visible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always:&lt;/strong&gt; Filters to published content only&lt;/li&gt;
&lt;/ul&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Recommended for page rendering&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;WithDisplayFilters&lt;/span&gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;News&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsContentAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Authentication Quick Reference&lt;/h3&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 0.9rem;&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Method&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Auth Mode&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Restricted Content&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Deleted/Expired&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;em&gt;(default)&lt;/em&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;SingleKey&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;No&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;No&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Public-facing pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;WithDisplayFilters()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Auto-detected&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Yes (if user detected)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;No (published only)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Page rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;AsUser(principal)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;SingleKey&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Yes (for that user)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;No&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;User-specific access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;WithAuth(options)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Configurable&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Yes (with BasicAuth)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Configurable&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Full control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Caching&lt;/h3&gt;
&lt;p&gt;The SDK caches Graph responses by default (5-minute absolute expiration). You can disable caching or configure custom options per query:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Disable caching&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;WithoutCache&lt;/span&gt;()

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Custom cache options&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;WithCacheOptions&lt;/span&gt;(options &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt;
{
    &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Configure cache duration, etc.&lt;/em&gt;&lt;/span&gt;
})&lt;/pre&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;10. Advanced Features&lt;/h2&gt;
&lt;h3&gt;Decay Functions - Time-Based Relevance &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Decay functions adjust document scores based on how far a DateTime field is from an origin value. Documents closer to the origin score higher, which can be useful for boosting recent content.&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;using static&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;Optimizely.Graph.Cms.Query.Linq.Request.GraphQueryFilter&lt;/span&gt;;

&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #0000cc;&quot;&gt;Decay&lt;/span&gt;(x.PublishDate, &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;DecayOptions&lt;/span&gt;
    {
        Origin = &lt;span style=&quot;color: #004d40;&quot;&gt;DateTime&lt;/span&gt;.UtcNow,
        Scale = &lt;span style=&quot;color: #800000;&quot;&gt;30&lt;/span&gt;,
        Rate = &lt;span style=&quot;color: #800000;&quot;&gt;0.5f&lt;/span&gt;
    }))
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Factor - Numeric Field Scoring &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Factor()&lt;/span&gt;&lt;/strong&gt; uses a numeric field&#39;s value to influence relevance scores. Useful for boosting documents with higher popularity, stock, or rating:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;using static&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;Optimizely.Graph.Cms.Query.Linq.Request.GraphQueryFilter&lt;/span&gt;;

&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; factorOptions = &lt;span style=&quot;color: #000080;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #004d40;&quot;&gt;FactorOptions&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;2.0f&lt;/span&gt;, &lt;span style=&quot;color: #004d40;&quot;&gt;FactorModifier&lt;/span&gt;.Sqrt);
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #0000cc;&quot;&gt;Factor&lt;/span&gt;(x.StockQuantity, factorOptions))

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Combine with other conditions&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #0000cc;&quot;&gt;Factor&lt;/span&gt;(x.StockQuantity, factorOptions) &lt;span style=&quot;color: #6b3a00;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x.InStock)&lt;/pre&gt;
&lt;h3&gt;Pinned Results &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Promote specific content items when search queries match configured phrases (similar to Search &amp;amp; Navigation&#39;s &quot;Best Bets&quot;):&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;getting started&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;WithPinned&lt;/span&gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// With explicit phrase and collection&lt;/em&gt;&lt;/span&gt;
.&lt;span style=&quot;color: #0000cc;&quot;&gt;WithPinned&lt;/span&gt;(phrase: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;getting started&quot;&lt;/span&gt;, collectionId: myCollectionId)&lt;/pre&gt;
&lt;h3&gt;Named Queries &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Assign a name to your query for logging, tracing, and Graph analytics:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;WithName&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;SearchPage_MainQuery&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Summary)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();&lt;/pre&gt;
&lt;h3&gt;Inspecting Generated GraphQL&lt;/h3&gt;
&lt;p&gt;Use &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt; at any point in the chain to see the GraphQL that would be sent:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;string&lt;/span&gt; graphql = &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;chocolate&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Category &lt;span style=&quot;color: #6b3a00;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Dessert&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;OrderBy&lt;/span&gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.PublishDate, &lt;span style=&quot;color: #004d40;&quot;&gt;OrderDirection&lt;/span&gt;.Descending)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Limit&lt;/span&gt;(&lt;span style=&quot;color: #800000;&quot;&gt;10&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;ToGraphQL&lt;/span&gt;();

&lt;span style=&quot;color: #660033;&quot;&gt;_logger&lt;/span&gt;.&lt;span style=&quot;color: #0000cc;&quot;&gt;LogDebug&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Generated GraphQL: {Query}&quot;&lt;/span&gt;, graphql);&lt;/pre&gt;
&lt;div style=&quot;border-left: 4px solid #16a34a; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dcfce7;&quot;&gt;&lt;strong&gt;Tip&lt;/strong&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt; is invaluable during development and debugging. Use it to verify your C# expressions produce the expected GraphQL, especially when building complex filter combinations.&lt;/p&gt;
&lt;/div&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;11. Working with Results &amp;amp; Untyped Queries&lt;/h2&gt;
&lt;h3&gt;IContentResult&amp;lt;T&amp;gt;&lt;/h3&gt;
&lt;p&gt;All queries return &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentResult&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;, which contains:&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 0.9rem;&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Property&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Type&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Items&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;The result items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Total&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;int&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Total matching items (when &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IncludeTotal()&lt;/span&gt;&lt;/strong&gt; is used)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Cursor&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;string&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Cursor for cursor-based pagination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Facets&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Facet data&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Aggregation results from &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Facet()&lt;/span&gt;&lt;/strong&gt; calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;TrackUrls&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Track URL data&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;URLs for search tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;CorrelationId&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;string&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Correlation ID for diagnostics&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;GetAsync() Variants&lt;/h3&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Standard execution with projected fields&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #004d40;&quot;&gt;IContentResult&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticleResult&lt;/span&gt;&amp;gt;(x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Title, x &lt;span style=&quot;color: #6b3a00;&quot;&gt;=&amp;gt;&lt;/span&gt; x.Author)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;();

&lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// Project to a different type at execution time&lt;/em&gt;&lt;/span&gt;
&lt;span style=&quot;color: #004d40;&quot;&gt;IContentResult&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;JsonElement&lt;/span&gt;&amp;gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Recipe&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Name&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Description&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;JsonElement&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
&lt;h3&gt;Streaming with GetAsContentAsyncEnumerable &lt;span style=&quot;display: inline-block; background: #16a34a; color: #fff; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; padding: 2px 7px; border-radius: 10px; margin-left: 6px; vertical-align: middle;&quot;&gt;New&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;For CMS content queries, stream results as fully resolved &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContent&lt;/span&gt;&lt;/strong&gt; objects:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;await foreach&lt;/span&gt; (&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; content &lt;span style=&quot;color: #000080;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;QueryContent&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;()
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsContentAsyncEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;ArticlePage&lt;/span&gt;&amp;gt;())
{
    &lt;span style=&quot;color: #2e2e2e;&quot;&gt;&lt;em&gt;// content is IContent, fully resolved through the CMS content loader&lt;/em&gt;&lt;/span&gt;
}&lt;/pre&gt;
&lt;h3&gt;Untyped / Dynamic Queries&lt;/h3&gt;
&lt;p&gt;When the content type isn&#39;t known at compile time, use the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Query(string)&lt;/span&gt;&lt;/strong&gt; entry point:&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;&lt;span style=&quot;color: #000080;&quot;&gt;var&lt;/span&gt; result = &lt;span style=&quot;color: #000080;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;_graphClient&lt;/span&gt;
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Query&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Recipe&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;SearchFor&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Chocolate Cake&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Where&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;CookingTime&quot;&lt;/span&gt;, &lt;span style=&quot;color: #004d40;&quot;&gt;ComparisonOperator&lt;/span&gt;.LessThan, &lt;span style=&quot;color: #800000;&quot;&gt;30&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;Fields&lt;/span&gt;(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Name&quot;&lt;/span&gt;, &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Description&quot;&lt;/span&gt;)
    .&lt;span style=&quot;color: #0000cc;&quot;&gt;GetAsync&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #004d40;&quot;&gt;JsonElement&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Generated GraphQL:&lt;/strong&gt;&lt;/p&gt;
&lt;pre style=&quot;background: #f4f4f5; color: #1e293b; border-radius: 8px; padding: 16px 20px; overflow-x: auto; margin: 16px 0; font-family: &#39;SF Mono&#39;,&#39;Cascadia Code&#39;,&#39;Fira Code&#39;,Consolas,&#39;Courier New&#39;,monospace; font-size: 0.85rem; line-height: 1.6;&quot;&gt;{
  &lt;span style=&quot;color: #0000cc;&quot;&gt;Recipe&lt;/span&gt;(
    &lt;span style=&quot;color: #660033;&quot;&gt;where&lt;/span&gt;: {
      &lt;span style=&quot;color: #0000cc;&quot;&gt;cookingTime&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;lt&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;30&lt;/span&gt; }
      &lt;span style=&quot;color: #0000cc;&quot;&gt;_fulltext&lt;/span&gt;: { &lt;span style=&quot;color: #660033;&quot;&gt;match&lt;/span&gt;: &lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Chocolate Cake&quot;&lt;/span&gt; }
    }
  ) {
    &lt;span style=&quot;color: #0000cc;&quot;&gt;items&lt;/span&gt; { &lt;span style=&quot;color: #0000cc;&quot;&gt;Name&lt;/span&gt;  &lt;span style=&quot;color: #0000cc;&quot;&gt;Description&lt;/span&gt; }
  }
}&lt;/pre&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 2px solid #e2e8f0;&quot;&gt;12. Complete Migration Reference&lt;/h2&gt;
&lt;p&gt;This table maps every Search &amp;amp; Navigation API to its Graph SDK equivalent. Use it as a quick reference during migration.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; margin: 16px 0; border-radius: 8px; border: 1px solid #e2e8f0;&quot;&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 0.9rem;&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Feature&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Search &amp;amp; Navigation API&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Graph SDK API&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Entry point&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;client.Search&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;_graphClient.QueryContent&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Graph SDK is injected via DI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Full-text search&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.For(&quot;query&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.SearchFor(&quot;query&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;All fields search&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.InAllField()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.UsingFullText()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Field-targeted search&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.InField(x =&amp;gt; x.Title, 2.0)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.UsingField(x =&amp;gt; x.Title, boost: 2)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Highlight&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithHighlight(spec)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.UsingFullText(highlightTag: &quot;&amp;lt;mark&amp;gt;&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (equality)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Category.Match(&quot;News&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Category == &quot;News&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (comparison)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Rating.GreaterThan(3))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Rating &amp;gt; 3)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (range)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Price.InRange(10, 50))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Price.InRange(10, 50))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (contains)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Title.Contains(&quot;text&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Title.Contains(&quot;text&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (starts with)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Title.Prefix(&quot;How&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Title.StartsWith(&quot;How&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (ends with)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Not directly supported&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Title.EndsWith(&quot;Guide&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (in collection)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Tag.In(values))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Tag.In(values))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (exists)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Title.Exists())&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Title.Exists())&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Filter (wildcard)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.Title.MatchWildcard(&quot;app*&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.Title.Like(&quot;app%&quot;))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Different wildcard syntax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Compound filter (AND)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; ...).Filter(x =&amp;gt; ...)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.A == &quot;a&quot; &amp;amp;&amp;amp; x.B == &quot;b&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Compound filter (OR)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Filter(x =&amp;gt; x.A.Match(&quot;a&quot;) | ...)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Where(x =&amp;gt; x.A == &quot;a&quot; || x.B == &quot;b&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Dynamic filters&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Combine Filter objects manually&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.BuildFilter&amp;lt;T&amp;gt;().And(...).Or(...)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Synonyms&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.UsingSynonyms()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Match(&quot;value&quot;, SynonymSlot.One)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Per-filter synonym support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;String facets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.TermsFacetFor(x =&amp;gt; x.Category)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Facet(x =&amp;gt; x.Category)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Date facets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.DateHistogramFacetFor(x =&amp;gt; x.Date, interval)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Facet(x =&amp;gt; x.Date, unit: FacetDateTimeUnit.DAY)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Numeric range facets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.RangeFacetFor(x =&amp;gt; x.Price, ranges)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Facet(x =&amp;gt; x.Price, ranges: buckets)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Boolean facets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Not available&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Facet(x =&amp;gt; x.IsFeatured)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;New in Graph SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Sort ascending&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderBy(x =&amp;gt; x.Date)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderBy(x =&amp;gt; x.Date, OrderDirection.Ascending)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Sort descending&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderByDescending(x =&amp;gt; x.Date)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderBy(x =&amp;gt; x.Date, OrderDirection.Descending)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Secondary sort&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ThenBy(x =&amp;gt; x.Title)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ThenBy(x =&amp;gt; x.Title, OrderDirection.Ascending)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Sort by relevance&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Not available&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderBy(&quot;_ranking&quot;, RankingMode.Relevance)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;New in Graph SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Pagination (skip)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Skip(20)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Skip(20)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Pagination (take)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Take(10)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Limit(10)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Total count&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Included by default&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.IncludeTotal()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Opt-in for performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Field projection&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Select(x =&amp;gt; new { x.Title })&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Fields&amp;lt;T&amp;gt;(x =&amp;gt; x.Title)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Autocomplete&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Via Statistics API&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Autocomplete(x =&amp;gt; x.Title, &quot;prefix&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Built into query API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Best bets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Via Best Bets UI&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithPinned()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Simplified API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Track search&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Track()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Track()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Locale&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Language(lang)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.SetLocale(&quot;en&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Execute (sync)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.GetResult()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;N/A&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Graph SDK is async-only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Execute (async)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.GetResultAsync()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.GetAsync()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Streaming&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Not available&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.GetAsyncEnumerable&amp;lt;T&amp;gt;(pageSize)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;New in Graph SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Single result&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Not available&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.GetSingleAsync()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;New in Graph SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Auth (display filters)&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Via display modes&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithDisplayFilters()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Auto-detects user context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3&gt;What&#39;s New (Graph SDK Only)&lt;/h3&gt;
&lt;p&gt;These features are available in the Graph SDK but &lt;strong&gt;did not exist&lt;/strong&gt; in Search &amp;amp; Navigation:&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 0.9rem;&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Feature&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;API&lt;/th&gt;
&lt;th style=&quot;background: #1e293b; color: #fff; font-weight: 600; text-align: left; padding: 10px 14px;&quot;&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Content Variations&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;SetVariation()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Query A/B test and personalization variants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;GraphQL Inspection&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;ToGraphQL()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;View the generated GraphQL query string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Cursor-Based Pagination&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Cursor&lt;/span&gt;&lt;/strong&gt; in &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContentResult&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Efficient deep pagination beyond skip/limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;IAsyncEnumerable Streaming&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsyncEnumerable&amp;lt;T&amp;gt;(pageSize)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Stream pages without loading all into memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Like Filter&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Like(&quot;app%&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;SQL-style wildcard patterns with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;%&lt;/span&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;_&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Boolean Facets&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.Facet(x =&amp;gt; x.IsFeatured)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Aggregate results by true/false values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Named Queries&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithName(&quot;name&quot;)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Tag queries for logging and Graph analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Cache Control&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithoutCache()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Per-query cache configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Cross-Type FilterBuilder&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.And&amp;lt;TSource, TOther&amp;gt;(expr)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Combine filters across different content types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Direct IContent Resolution&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetAsContentAsyncEnumerable&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Resolve Graph results directly to &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IContent&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Decay Functions&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where(x =&amp;gt; Decay(field, options))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Time-based relevance scoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Factor&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Where(x =&amp;gt; Factor(field, options))&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Numeric field relevance scoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Pinned Results&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;WithPinned(phrase, collectionId)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Promote content for specific search phrases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Opt-In Total Count&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IncludeTotal()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Only calculate total when needed (perf opt)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;GetSingleAsync&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;GetSingleAsync()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Return exactly one result or throw&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;ThenBy&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ThenBy(x =&amp;gt; x.Field, direction)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Secondary sort criteria after &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;OrderBy()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Ranking Mode&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.OrderBy(&quot;_ranking&quot;, RankingMode.Relevance)&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Sort by relevance, boost, or index order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;WithDisplayFilters&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.WithDisplayFilters()&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 9px 14px; border-bottom: 1px solid #e2e8f0; vertical-align: top;&quot;&gt;Context-aware auth that auto-detects user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr style=&quot;border: none; border-top: 1px solid #e2e8f0; margin: 40px 0;&quot; /&gt;
&lt;h2 style=&quot;font-size: 1.65rem; font-weight: bold; color: #0f172a; margin-top: 56px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: none;&quot;&gt;Looking Ahead&lt;/h2&gt;
&lt;p&gt;The Graph SDK already covers the vast majority of Search &amp;amp; Navigation query patterns. For most CMS content query scenarios (filtering, full-text search, faceting, sorting, pagination, autocomplete, and search tracking) you can migrate your existing code with straightforward API mapping.&lt;/p&gt;
&lt;p&gt;Additional capabilities are being added with each release. The SDK is actively evolving based on partner feedback and real-world migration experiences. If you encounter a pattern from Search &amp;amp; Navigation that doesn&#39;t have a direct equivalent yet, the Optimizely team wants to hear about it.&lt;/p&gt;
&lt;h3&gt;Next Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Add the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Optimizely.Graph.Cms.Query&lt;/span&gt;&lt;/strong&gt; package to your CMS 13 project.&lt;/li&gt;
&lt;li&gt;Register with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;services.AddGraphContentClient()&lt;/span&gt;&lt;/strong&gt; in your startup.&lt;/li&gt;
&lt;li&gt;Inject &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;IGraphContentClient&lt;/span&gt;&lt;/strong&gt; and start querying.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt; to inspect generated queries as you learn.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/v1.4.0-optimizely-graph/docs&quot;&gt;Optimizely Graph Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/6c9478a8761c41d88dfc32e9ef56e714.aspx&quot;&gt;Optimizely World&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;border-left: 4px solid #16a34a; border-radius: 4px; padding: 16px 20px; margin: 20px 0; font-size: 0.93rem; background: #dcfce7;&quot;&gt;&lt;strong&gt;Key tip for your migration&lt;/strong&gt;
&lt;p&gt;Start with &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;.ToGraphQL()&lt;/span&gt;&lt;/strong&gt;. Write your Graph SDK queries, inspect the generated GraphQL, and compare it to what you expect. This feedback loop will build your confidence quickly and help you verify that your migrated queries produce the correct results.&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin-top: 32px; font-size: 0.85rem; color: #888; font-style: italic;&quot;&gt;This guide is based on the &lt;strong&gt;&lt;span style=&quot;color: #8b0000;&quot;&gt;Optimizely.Graph.Cms.Query&lt;/span&gt;&lt;/strong&gt; SDK for Optimizely CMS 13. API details reflect the current SDK version and may evolve in future releases.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/jake-minard/dates/2026/3/introducing-optimizely-cms-13-graph-sdk/</guid>            <pubDate>Wed, 25 Mar 2026 02:51:18 GMT</pubDate>           <category>Blog post</category></item><item> <title>AEO/GEO in a Legacy Optimizely CMS Project: A Practical Pattern for Google, ChatGPT, and Claude</title>            <link>https://wseweryn.dev/blog/2026-03-23-geo-aeo-vs-seo-optimizely-ai/</link>            <description>A practical Optimizely CMS pattern for AEO/GEO on legacy sites: shared page metadata, Razor-rendered JSON-LD, crawler-aware robots.txt, and Scheduled Jobs for gradual enrichment.</description>            <guid>https://wseweryn.dev/blog/2026-03-23-geo-aeo-vs-seo-optimizely-ai/</guid>            <pubDate>Mon, 23 Mar 2026 00:00:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>Schema.org as Native CMS Properties</title>            <link>https://stuartgreig.dev/blog/schemaorg-as-native-cms-properties-a-pattern-for-optimizely/</link>            <description>Learn how to implement Schema.org structured data as native Optimizely CMS properties. Move SEO from hardcoded templates to a validated, content-managed model</description>            <guid>https://stuartgreig.dev/blog/schemaorg-as-native-cms-properties-a-pattern-for-optimizely/</guid>            <pubDate>Fri, 20 Mar 2026 14:55:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>Integrating Searchspring with Optimizely – Part 1: Architecture &amp; Setup</title>            <link>https://www.wiselinjayajos.com/integrating-searchspring-with-optimizely-part-1-architecture-and-setup</link>            <description>Integrating Searchspring with Optimizely – Part 1: Architecture &amp; Setup</description>            <guid>https://www.wiselinjayajos.com/integrating-searchspring-with-optimizely-part-1-architecture-and-setup</guid>            <pubDate>Fri, 20 Mar 2026 12:38:23 GMT</pubDate>           <category>Blog post</category></item><item> <title>CMS 13 Preview 4 — Upgrading from Preview 3</title>            <link>https://world.optimizely.com/blogs/robert-svallin/dates/2026/3/cms-13-preview-4--upgrading-from-preview-3/</link>            <description>&lt;p&gt;This is the third post in a series where I use the Alloy template as a reference to walk through each CMS 13 preview. The &lt;a href=&quot;/link/401767d8a5e8446db6e213b139618c2d.aspx&quot;&gt;first post&lt;/a&gt; covered upgrading from CMS 12 to Preview 2, and the &lt;a href=&quot;/link/440e06e8b64e4e80aa1b65dc833d9ec2.aspx&quot;&gt;second&lt;/a&gt; looked at the key changes in Preview 3. If you&#39;re following along, pick up where we left off.&lt;/p&gt;
&lt;p&gt;Preview 4 is out. The package bump is easy enough, but there&#39;s an API change around how you resolve the start page that&#39;ll ripple through your code. Here&#39;s what to change and what&#39;s worth knowing about.&lt;/p&gt;
&lt;h2&gt;Step 1: Update Packages&lt;/h2&gt;
&lt;p&gt;Bump your package references from preview3 to preview4:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.CMS&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;
&amp;lt;PackageReference Include=&quot;EPiServer.CMS.UI.AspNetIdentity&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;
&amp;lt;PackageReference Include=&quot;Optimizely.Graph.Cms&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;h3&gt;Known Issue: Database Schema Upgrade from Older CMS 12 Versions&lt;/h3&gt;
If you&#39;re upgrading directly from an older CMS 12 version (e.g. 12.34.1 or earlier) to a CMS 13 preview and not from preview3 (which this article assumes), the database schema migration may fail with an error like:&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;Column names in each table must be unique. Column name &#39;Failed&#39; in table &#39;dbo.tblNotificationMessage&#39; is specified more than once.&lt;/code&gt;&lt;/pre&gt;
This happens because certain columns were added in later CMS 12 releases, and the CMS 13 migration scripts don&#39;t check whether they already exist before trying to add them.&lt;br /&gt;
&lt;div&gt;Workaround: First upgrade to the latest CMS 12 version so that your database schema is fully up to date, then upgrade from there to the CMS 13 preview. This ensures all intermediate schema changes are applied before the CMS 13 migration runs.&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Step 2: Resolving the Start Page&lt;/h2&gt;
&lt;p&gt;In Preview 3, Alloy template resolved the start page by casting to Website and accessing RoutingEntryPoint. In Preview 4, the simplest approach is to use ContentReference.StartPage directly &amp;mdash; no need to go through IApplicationResolver in most cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before (Preview 3)&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var website = _applicationResolver.GetByContext() as Website;
var startPageContentLink = website?.RoutingEntryPoint;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;After (Preview 4)&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var startPageContentLink = ContentReference.StartPage;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the Alloy template this simplified things across several files by using ContentReference.StartPage&amp;nbsp;&lt;br /&gt;- &lt;strong&gt;PageViewContextFactory.cs&lt;/strong&gt; &amp;mdash; CreateLayoutModel&amp;nbsp;&lt;br /&gt;-&amp;nbsp;&lt;strong&gt;ContentLocator.cs&lt;/strong&gt; &amp;mdash; GetContactPages&amp;nbsp;&lt;br /&gt;- &lt;strong&gt;PreviewController.cs&lt;/strong&gt; &amp;mdash; the Index action&lt;br /&gt;- &lt;strong&gt;StartPageController.cs&lt;/strong&gt; &amp;mdash; the Index action&lt;br /&gt;-&amp;nbsp;&lt;strong&gt;Breadcrumbs.cshtml&lt;/strong&gt; and &lt;strong&gt;Header.cshtml&lt;/strong&gt;&amp;nbsp;&amp;mdash; same change&lt;/p&gt;
&lt;p&gt;If you do need more control, IRoutableApplication with its EntryPoint property is still available as an alternative.&lt;/p&gt;
&lt;p&gt;The SiteDefinition migration keeps getting refined. Issues with default application provisioning and hostname resolution between preview and view modes from earlier previews have been sorted out.&lt;/p&gt;
&lt;h2&gt;Step 3: DAM Integration (optional)&lt;/h2&gt;
&lt;p&gt;Preview 4 adds a new package for Optimizely DAM integration. Its important to call out that even though DAM is a fundamental piece of CMS 13 it is possible to run without it. CMS still can store assets in te traditional sense.&lt;/p&gt;
&lt;p&gt;Similar to CMS 12 the DAM configuration is handled using options directly requiring an application to be created in CMP from which the credentials can be retrieved for configuration in CMS. You&#39;ll also need the SSO ID which can be found under &lt;strong&gt;Settings \ Organization \ General&lt;/strong&gt; in CMP.&lt;/p&gt;
&lt;p&gt;The DAM integration no longer talks to the CMP REST API directly. Instead it&#39;s built on External Sources, which means DAM assets need to be indexed into the Optimizely Graph instance connected to your CMS. So before wiring up the code below, make sure you have Optimizely Graph set up, then contact Optimizely Support to connect DAM to your Graph instance. The onboarding steps &amp;mdash; selecting your DAM instance, activating asset types &amp;mdash; follow the same process as CMS SaaS and are documented in the &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.0.0-CMS-SaaS/docs/onboard-dam-to-cms-saas&quot;&gt;Onboard DAM to CMS guide&lt;/a&gt;. Updated documentation specific to CMS 13 will be available at release. Once that&#39;s done, Content Manager can be used to discover and pick DAM assets directly from the editing UI.&lt;/p&gt;
&lt;p&gt;Add the package:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.Cms.DamIntegration.UI&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Register the DAM UI in Startup.cs:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;services.AddDamUI();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the DAM HTML helpers namespace to Views/_ViewImports.cshtml:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@using EPiServer.Cms.DamIntegration.UI.Helpers&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives you access to helpers like RenderTagWithMetadata(...) for rendering DAM assets. Note that the epi-property tag helper you&#39;re already using comes from EPiServer.Cms.AspNetCore.TagHelpers, which should already be registered in your _ViewImports.cshtml via @addTagHelper.&lt;/p&gt;
&lt;p&gt;Then configure your CMP credentials (note that these have defaults, included here for transparency) in appsettings.json:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&quot;Optimizely&quot;: {
  &quot;Cms&quot;: {
    &quot;DamUI&quot;: {
      &quot;Endpoint&quot;: &quot;https://cmp.optimizely.com&quot;,
      &quot;SsoId&quot;: &quot;&amp;lt;your-sso-id&amp;gt;&quot;,
      &quot;NavigationUrl&quot;: &quot;https://cmp.optimizely.com/cloud/library&quot;
    }
  },
  &quot;Cmp&quot;: {
    &quot;Client&quot;: {
      &quot;TokenUrl&quot;: &quot;https://accounts.cmp.optimizely.com/o/oauth2/v1/token&quot;,
      &quot;ApiUrl&quot;: &quot;https://api.cmp.optimizely.com/v3/&quot;,
      &quot;ClientId&quot;: &quot;&amp;lt;your-client-id&amp;gt;&quot;,
      &quot;ClientSecret&quot;: &quot;&amp;lt;your-client-secret&amp;gt;&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The DAM picker now also supports multi-select, which is a nice improvement for editors working with lots of media.&lt;/p&gt;
&lt;h3&gt;Migrating from CMS 12 DAM Integration&lt;/h3&gt;
&lt;p&gt;For the GA release of CMS 13, a standalone migration package will be available that converts the CMS 12-style DAM integration to the new one. This package&amp;nbsp;will handle the migration of existing DAM asset references so that they work with the new EPiServer.Cms.DamIntegration.UI package.&lt;/p&gt;
&lt;p&gt;The first version of the migration package will support:&lt;br /&gt;&amp;nbsp; - ContentReference properties&lt;br /&gt;&amp;nbsp; - IList&amp;lt;ContentReference&amp;gt; properties&lt;/p&gt;
&lt;p&gt;Support for additional property types will be added in future releases.&lt;/p&gt;
&lt;h3&gt;Using DAM Assets in Your Content&lt;/h3&gt;
&lt;p&gt;To use DAM assets on a page, add a ContentReference property with the UIHint.Image hint:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using EPiServer.Web;
using System.ComponentModel.DataAnnotations;

public class DamExamplePage : StandardPage
{
    [Display(GroupName = Globals.GroupNames.Content)]
    [UIHint(UIHint.Image)]
    public virtual ContentReference Image { get; set; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the view, render it with the epi-property tag helper &amp;mdash; same pattern as any other CMS property:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;img epi-property=&quot;@Model.CurrentPage.Image&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 4: Audiences (optional)&lt;/h2&gt;
&lt;p&gt;Audiences are a separate package in CMS 13. If you were using services.AddVisitorGroups() in Preview 3, you&#39;ll need to add the new NuGet package and update your service registration.&lt;/p&gt;
&lt;p&gt;Add the package:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;PackageReference Include=&quot;EPiServer.Cms.UI.VisitorGroups&quot; Version=&quot;13.0.0-preview4&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then update your Startup.cs &amp;mdash; the old AddVisitorGroups() call is replaced with two separate registrations:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using EPiServer.Cms.UI.VisitorGroups;
services.AddVisitorGroupsMvc().AddVisitorGroupsUI();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few audience-related bugs have also been fixed: the policy-not-found error is gone, Geographic Location criteria works, and context menu positioning for personalized groups has been corrected.&lt;/p&gt;
&lt;h2&gt;What Else Is New in Preview 4&lt;/h2&gt;
&lt;p&gt;A few things worth knowing about beyond the upgrade steps:&lt;/p&gt;
&lt;h3&gt;Graph .NET SDK&lt;/h3&gt;
&lt;p&gt;There&#39;s a new .NET SDK for Optimizely Graph with a fluent API covering facets, caching, auth, tracking, and object-to-Graph field mapping. Extensibility points have also been added to ContentGraph.CMS so you can hook into the indexing pipeline.&lt;/p&gt;
&lt;h3&gt;Improved Migration from SiteDefinition&lt;/h3&gt;
&lt;p&gt;The migration from SiteDefinition to the Application Model has been improved. Creating in-process websites via the settings UI works again, and typed content types now show up correctly when picking the start page for an application.&lt;/p&gt;
&lt;p&gt;For the full list of changes, check the official release notes.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/robert-svallin/dates/2026/3/cms-13-preview-4--upgrading-from-preview-3/</guid>            <pubDate>Fri, 20 Mar 2026 12:08:15 GMT</pubDate>           <category>Blog post</category></item><item> <title>The move to CMS 13: Upgrade Notes for Technical Teams</title>            <link>https://hristo.vercel.app/blogs/cms-13-practical-upgrade-plan</link>            <description>A technical walkthrough of CMS 13 preview3 and headless work: what is changing, where the risks are, and how an upgrade and what to expect</description>            <guid>https://hristo.vercel.app/blogs/cms-13-practical-upgrade-plan</guid>            <pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>Customizing Product Data Sent to Optimizely Product Recommendations in Optimizely Commerce</title>            <link>https://wseweryn.dev/blog/2026-03-20-customizing-product-data-for-optimizely-product-recommendations/</link>            <description>A practical guide to customizing IEntryAttributeService in Optimizely Commerce so you can override product titles, add custom feed attributes, and keep safe fallbacks to the default behavior.</description>            <guid>https://wseweryn.dev/blog/2026-03-20-customizing-product-data-for-optimizely-product-recommendations/</guid>            <pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>