<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by K Khan </title><link href="http://world.optimizely.com" /><updated>2025-02-14T11:22:03.0000000Z</updated><id>https://world.optimizely.com/blogs/K-Khan-/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Comerce Connect calatog caching settings</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2025/2/comerce-connect-calatog-caching-settings/" /><id>&lt;p&gt;A critical aspect of Commerce Connect is the caching mechanism for the product catalog, which enhances performance by reducing database load and improving data retrieval times. By effectively configuring and managing the catalog caching mechanisms in Optimizely Commerce Connect, applications can achieve improved performance, reduce server load, and ensure that users receive up-to-date catalog.&lt;/p&gt;
&lt;h1&gt;Catalog Caching Configurations&lt;/h1&gt;
&lt;p&gt;These settings help manage how long different types of catalog data are stored in the cache before expiration, thereby optimizing data retrieval and system performance.&lt;/p&gt;
&lt;h3&gt;Commerce Connect V13&lt;/h3&gt;
&lt;p&gt;Caching for each subsystem, including catalogs and orders, is configured within its respective configuration files. For example, caching for catalogs can be found in &lt;em&gt;ecf.catalog.config&lt;/em&gt; located in the site&#39;s &lt;em&gt;configs&lt;/em&gt; folder.&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;&amp;lt;Cache enabled=&quot;true&quot; 
       collectionTimeout=&quot;0:5:0&quot; 
       entryTimeout=&quot;0:5:0&quot;
       nodeTimeout=&quot;0:5:0&quot; 
       schemaTimeout=&quot;1:0:0&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Commerce Connect V14&lt;/h3&gt;
&lt;p&gt;&amp;nbsp;Cache settings for the Catalogs subsystem, using AppSettings.json&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;&quot;EPiServer&quot;: {
       &quot;Commerce&quot;: {
          &quot;CatalogOptions&quot;: {
            &quot;Cache&quot;: {
              &quot;UseCache&quot;: true,
              &quot;ContentVersionCacheExpiration&quot;: &quot;00:05:00&quot;,
              &quot;CollectionCacheExpiration&quot;: &quot;00:05:00&quot;,
              &quot;EntryCacheExpiration&quot;: &quot;00:05:00&quot;,
              &quot;NodeCacheExpiration&quot;: &quot;00:05:00&quot;
            }
          }
       }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cache settings for the Catalogs subsystem can be used using Startup also.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public void ConfigureServices(IServiceCollection services)
    {
        services.Configure&amp;lt;CatalogOptions&amp;gt;(o =&amp;gt;
        {
            o.Cache.UseCache = true;
            o.Cache.ContentVersionCacheExpiration = TimeSpan.FromMinutes(05);
            o.Cache.CollectionCacheExpiration = TimeSpan.FromMinutes(05);
            o.Cache.EntryCacheExpiration = TimeSpan.FromMinutes(05);
            o.Cache.NodeCacheExpiration = TimeSpan.FromMinutes(05);
        });
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;UseCache: Enables or disables caching.&lt;/li&gt;
&lt;li&gt;ContentVersionCacheExpiration: Sets the cache duration for content versions.&lt;/li&gt;
&lt;li&gt;CollectionCacheExpiration: Defines the cache duration for an array of entries. The cached data primarily consists of CatalogEntryDto objects. Since the Entry object is derived from the Data Transfer Object (DTO), the DTO itself is cached. However, it is also possible to cache the Entry objects directly instead of the DTO in some cases.&lt;/li&gt;
&lt;li&gt;EntryCacheExpiration: Specifies the cache duration for individual catalog entries. The cached data primarily consists of CatalogEntryDto objects.&lt;/li&gt;
&lt;li&gt;NodeCacheExpiration: Determines the cache duration for catalog nodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cache Invalidation&lt;/h2&gt;
&lt;p&gt;Cache invalidation ensures that outdated or modified data does not persist in the cache, maintaining data consistency. In the catalog subsystem, the cache is invalidated under the following circumstances:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Expiration&lt;/strong&gt;: Cached data is automatically invalidated when it reaches the specified timeout duration.&lt;br /&gt;&lt;strong&gt;Data Updates&lt;/strong&gt;: If a catalog object is updated, the corresponding cache entries are invalidated to reflect the changes.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;References:&amp;nbsp;&lt;a href=&quot;https://docs.developers.optimizely.com/customized-commerce/docs/caching&quot;&gt;https://docs.developers.optimizely.com/customized-commerce/docs/caching&lt;/a&gt;&lt;/p&gt;</id><updated>2025-02-14T11:22:03.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Dynamic packages in Commerce Connect</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/11/support-for-dynamic-packages-in-commerce-connect/" /><id>&lt;p&gt;In Optimizely Commerce Connect, you can group different items using packages and bundles.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Package: A package has one or more versions of a product (called variants) and possibly other packages. It has one SKU (a unique code) and one price. When you add a package to a shopping cart, it appears as a single item.&lt;/li&gt;
&lt;li&gt;Bundle: A bundle is a group of packages, products, and variants, each with its price. Unlike packages, each item in a bundle appears separately in the cart, allowing customers to buy several items at once but treat each as its cart item&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;From EPiServer.Commerce 14.29.0 you can have dynamic packages&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dynamic Package (beta): This is similar to a regular package but gives customers more choices. It includes multiple products, each with one or more variants, and has a single SKU and price. Customers can choose which version (variant) of each product they want in the package. Like a regular package, it shows up as one item in the cart.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Dynamic Packages&amp;nbsp;&lt;/h1&gt;
&lt;p&gt;There are many use cases where dynamic packages help. A very common use case is when customers are selecting some internet service provider along with a phone line or TV, Telecom companies allow users to dynamically create packages based on their service needs, combining internet, cable, and phone services.&lt;/p&gt;
&lt;p&gt;On a travel website, customers can create their travel packages by selecting a combination of flights, hotels, car rentals, and activities. This dynamic packaging enables customers to tailor their trip based on their budget, preferred airlines, hotel standards, and desired experiences.&lt;/p&gt;
&lt;p&gt;The dynamic packages feature in Commerce Connect is currently in beta from 14.29.0. It is disabled by default.&lt;/p&gt;
&lt;p&gt;Developer&#39;s documentation: &lt;a href=&quot;https://docs.developers.optimizely.com/customized-commerce/docs/dynamic-packages&quot;&gt;https://docs.developers.optimizely.com/customized-commerce/docs/dynamic-packages&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</id><updated>2024-11-01T12:22:28.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>keep special characters in URL</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/9/keep-special-characters-in-url/" /><id>&lt;p&gt;When creating a page, the default URL segment validation automatically replaces special characters with their standard equivalents (e.g., &quot;&amp;auml;&quot; is replaced with &quot;a&quot;). However, some clients may require these special characters to remain intact in URLs for non-English versions of their website.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var validChars = &quot;&amp;uuml; &amp;ouml; &amp;auml; &amp;szlig; &amp;oacute; &amp;ntilde; &amp;aacute; &amp;aacute; &amp;eacute; &amp;iacute; &amp;oacute; ő &amp;uacute; &amp;uuml; &amp;ntilde;&quot;; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For CMS 12&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//Startup.cs
services.Configure&amp;lt;UrlSegmentOptions&amp;gt;(config =&amp;gt; {
    config.SupportIriCharacters = true;
    config.ValidCharacters = @&quot;A-Za-z0-9\-_~\.\$&quot; + validChars;
}); &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For CMS 11&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class UrlSegmentConfigurationModule : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        var validChars = &quot;&amp;uuml; &amp;ouml; &amp;auml; &amp;szlig; &amp;oacute; &amp;ntilde; &amp;aacute; &amp;aacute; &amp;eacute; &amp;iacute; &amp;oacute; ő &amp;uacute; &amp;uuml; &amp;ntilde;&quot;; 
        context.Services.RemoveAll&amp;lt;UrlSegmentOptions&amp;gt;();
        context.Services.AddSingleton&amp;lt;UrlSegmentOptions&amp;gt;(s =&amp;gt; new UrlSegmentOptions
        {
            SupportIriCharacters = true,
            ValidCharacters = @&quot;\p{L}0-9\-_~\.\$&quot; + validChars
        });
    }

    public void Initialize(InitializationEngine context){}

    public void Uninitialize(InitializationEngine context) { }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://support.optimizely.com/hc/en-us/articles/115005062883-Enable-special-characters-in-URL-Segment&quot;&gt;https://support.optimizely.com/hc/en-us/articles/115005062883-Enable-special-characters-in-URL-Segment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/a5c3e4adc40b463f91f27b7092631e27.aspx&quot;&gt;https://world.optimizely.com/blogs/Minesh-Shah/Dates/2023/2/url-rewrites-in-cms12--net-6-/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/International/articles/idn-and-iri/&quot;&gt;An Introduction to Multilingual Web Addresses&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</id><updated>2024-09-19T16:47:59.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Opti ID overview</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/7/opti-id-overview/" /><id>&lt;p&gt;Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your users from one place. you can watch an interactive demo &lt;a href=&quot;https://optimizely.navattic.com/awr50u0h&quot;&gt;here&lt;/a&gt;.&amp;nbsp; The Optimizely platform offers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A single login (Single Sign-On or SSO) with support for multi-factor authentication (MFA), using your own MFA setup and directory authentication provider.&lt;/li&gt;
&lt;li&gt;The ability to switch between apps without having to log in again.&lt;/li&gt;
&lt;li&gt;The option to manage users, groups, and roles with Opti ID.&lt;/li&gt;
&lt;li&gt;A dashboard for managing account information, usage, and billing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Opti ID is currently available for the following Optimizely products:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commerce Connect&lt;/li&gt;
&lt;li&gt;Configured Commerce&lt;/li&gt;
&lt;li&gt;Content Management System (CMS 12)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Optimizely CMS SaaS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Content Marketing Platform (CMP)&lt;/li&gt;
&lt;li&gt;Digital Experience Platform (DXP)&lt;/li&gt;
&lt;li&gt;Experimentation&lt;/li&gt;
&lt;li&gt;Experiment Collaboration&lt;/li&gt;
&lt;li&gt;Optimizely Data Platform (ODP)&lt;/li&gt;
&lt;li&gt;Product Information Management (PIM)&lt;/li&gt;
&lt;li&gt;Product Recommendations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is easy to set up Opti ID in your solution with the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install the NuGet Package:&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;dotnet add package EPiServer.OptimizelyIdentity&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable Opti ID:&lt;/strong&gt; In your Startup.cs file, add the following line in the ConfigureServices method to enable Opti ID globally&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;services.AddOptimizelyIdentity(useAsDefault: true);&lt;/code&gt;&lt;/pre&gt;
This makes Opti ID, active throughout the application, including in shell modules, preview, and edit modes. You can customize authentication schemes using &lt;strong&gt;AuthenticationOptions&lt;/strong&gt; if needed.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remove Unnecessary Services:&lt;/strong&gt; If you&#39;re not using ASP.NET Identity, remove any calls to &lt;strong&gt;services.AddCmsAspNetIdentity()&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Virtual Roles:&lt;/strong&gt; Opti ID automatically maps the virtual roles CmsEditors and CmsAdmins.&amp;nbsp;If you already have these mappings, you&#39;ll need to remove them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing:&lt;/strong&gt; Ensure your user is assigned to at least one built-in system role for the CMS before testing. Deploy your changes to DXP or run the application locally with Opti ID set up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Running Opti ID Locally:&lt;/strong&gt; &lt;a href=&quot;https://localhost:7595&quot;&gt;&lt;/a&gt;To configure local usage, add these settings in your appsettings.json file. These are automatically provided when deploying to the Optimizely Digital Experience Platform (DXP) or can be found in the DXP Management Portal under API &amp;gt; Opti ID dev key&lt;/p&gt;
&lt;div class=&quot;overflow-y-auto p-4&quot;&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;{
  &quot;EPiServer&quot;: {
    &quot;Cms&quot;: {
      &quot;OptimizelyIdentity&quot;: {
        &quot;InstanceId&quot;: &quot;xxx&quot;,
        &quot;ClientId&quot;: &quot;xxx&quot;,
        &quot;ClientSecret&quot;: &quot;xxx&quot;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Opti ID will work locally with the following ports:&lt;/p&gt;
&lt;p&gt;https://localhost:5000&lt;br /&gt;https://localhost:5096&lt;br /&gt;https://localhost:6921&lt;br /&gt;&lt;a href=&quot;https://localhost:7595&quot;&gt;https://localhost:7595&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;References: https://support.optimizely.com/hc/en-us/articles/12613241464461-Get-started-with-Opti-ID&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;</id><updated>2024-07-26T09:35:21.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Optimizely Forms: Safeguarding Your Data</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/5/episerver-forms-safeguarding-your-data/" /><id>&lt;p&gt;With the rise of cyber threats and privacy concerns, safeguarding sensitive information has become a top priority for businesses across all industries. As organizations collect and manage data through various channels, ensuring the security of online forms has become crucial. Optimizely Forms, offers a robust solution for creating and managing forms, but how does it fare in terms of security?&lt;/p&gt;
&lt;p&gt;Content authors can design multiple kinds of forms, Whether it&#39;s collecting customer feedback, processing orders, gathering leads, or forms that may contain sensitive data. Sensitive information submitted through forms could be vulnerable to various threats, including data breaches, unauthorized access, and manipulation. Forms can ask users to upload files, a user-uploaded file can also be a threat or a sensitive document.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Optimizely Forms offers a comprehensive set of security features, customizations, and capabilities to protect user data and mitigate security risks. However, ensuring security is a shared responsibility and requires a proactive approach, encompassing continuous monitoring, updates, and adherence to best practices to safeguard against evolving threats and developers and editor&#39;s training.&lt;/p&gt;
&lt;p&gt;To address security concerns, Optimizely Forms offers several built-in or customizable security features, including &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/encrypting-form-data&quot;&gt;data encryption&lt;/a&gt;, &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/creating-new-data-storage-mechanism&quot;&gt;data storage mechanisms&lt;/a&gt;, v&lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/creating-form-element-with-validator&quot;&gt;alidation and sanitization&lt;/a&gt;, &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/configuring-optimizely-forms&quot;&gt;limited access control&lt;/a&gt;, CAPTCHA Integration, and &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/customizing-retention-policies&quot;&gt;data retention policies&lt;/a&gt;. It is &lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/v1.2.0-forms/docs/webhooks-actor&quot;&gt;not required to store data&lt;/a&gt; within the CMS database. Those should be considered while implementing and using Forms.&lt;/p&gt;
&lt;p&gt;Organizations can enhance the security of Optimizely Forms by following these best practices:&lt;/p&gt;
&lt;p&gt;User Education: Educate users about security best practices, such as creating strong passwords, recognizing phishing attempts, and exercising caution when sharing sensitive information via Optimizely Forms. e.g. If submitted data is stored in Forms, then it will be visible to any editors who have access to CMS regardless the data is related or not. User-uploaded files can appear in Search results within the CMS or globally if not taken care of.&lt;/p&gt;
&lt;p&gt;Regular Updates: Stay vigilant about applying software updates and patches released by Optimizely to address known vulnerabilities and security flaws in Optimizely Forms.&lt;/p&gt;
&lt;p&gt;Strong Authentication: Implement strong authentication mechanisms, such as multi-factor authentication (MFA), to verify the identities of users accessing Optimizely Forms backend interfaces and administrative dashboards.&lt;/p&gt;
&lt;p&gt;Security Testing: Conduct regular security assessments, including penetration testing and vulnerability scanning, to identify and remediate potential security weaknesses in Optimizely Forms implementations.&lt;/p&gt;
&lt;p&gt;Malware Scan for User uploaded files: Implement &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/defender-for-cloud/defender-for-storage-malware-scan&quot;&gt;scanning&lt;/a&gt; of user-uploaded files, solutions will be different, depending on the infrastructure.&lt;/p&gt;</id><updated>2024-05-16T07:48:22.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Top tip: Better, do not save EPiServer.Foms submissions for sensitive data</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/3/toptip-stop-indexing-users-uploaded-files/" /><id>&lt;p&gt;&lt;span&gt;If your website utilizes EPiServer.Forms and includes forms where users can upload files, there is a significant probability that the Find/Search Indexing Job will also index those files. Consequently, these files may become accessible through searches facilitated by Find. Editors navigating the Editor area may encounter these files when searching for images, potentially leading to public availability of search results also depending on implementations. To address this issue, a straightforward solution is to cease indexing user-uploaded files. One possible approach to prevent the indexing of uploaded files from forms is outlined in the code below.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;ContentIndexer.Instance.Conventions.ForInstancesOf&amp;lt;IContentMedia&amp;gt;().ShouldIndex(x =&amp;gt; 
     _contentLoader.GetAncestors(documentFileBase.ParentLink).Select(x=&amp;gt;x.Name).Contains( EPiServer.Forms.Constants.FileUploadFolderName));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will stop indexing users&#39; uploaded files, and certainly slow down the indexing job as we will be loading ancestors.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It&#39;s important to note that despite this adjustment, users&#39; uploaded files will remain accessible to all editors through the Form Submissions View. Depending on the sensitivity of the uploaded user&#39;s data, it&#39;s imperative to consider this accessibility. Ideally, in cases where user data is sensitive, refrain from saving form submissions within forms due to the limited security associated with form submissions. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Editors play a pivotal role in designing forms, and their training is crucial, particularly in alignment with the nature of the business, the type of information they will be gathering, and the relevant legislation. Training should ensure that editors understand the intricacies of data collection, its implications, and compliance requirements.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</id><updated>2024-03-22T10:27:12.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Toptip - what is .well-known folder</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2024/1/toptip----well-known-folder/" /><id>&lt;p&gt;&lt;span&gt;Within your &lt;/span&gt;&lt;code&gt;~/public&lt;/code&gt;&lt;span&gt; folder, you may come across a directory named &quot;.well-known.&quot; This directory is frequently employed in web-based protocols to retrieve &quot;site-wide metadata&quot; related to a host before initiating a request. It&#39;s important to note that the absence of this folder doesn&#39;t necessarily indicate an issue; it simply means it hasn&#39;t been utilized or generated yet.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here are some examples of what you might find in the &quot;.well-known&quot; directory:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;.well-known/security.txt:&lt;/strong&gt; Contains information about a website&#39;s security policies and &lt;a href=&quot;https://securitytxt.org/&quot;&gt;contact information for security researchers&lt;/a&gt;.&lt;br /&gt;Please read some helpful blogs on this topic.&lt;br /&gt;&lt;a href=&quot;https://www.gulla.net/en/blog/security.txt&quot;&gt;https://www.gulla.net/en/blog/security.txt&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://optimizely.blog/2023/03/easy-implementation-of-security.txt-with-minimal-api-.net-core&quot;&gt;https://optimizely.blog/2023/03/easy-implementation-of-security.txt-with-minimal-api-.net-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;.well-known/apple-app-site-association (AASA):&lt;/strong&gt; Used for &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html&quot;&gt;associating iOS apps with websites&lt;/a&gt;, enabling features like Universal Links. This file doesn&#39;t have an extension.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.well-known/assetlinks.json: &lt;/strong&gt;&lt;span&gt;Used in the context of Android App Links. &lt;a href=&quot;https://developer.android.com/training/app-links/verify-android-applinks&quot;&gt;Android App Links&lt;/a&gt; are a way to associate a website with a specific Android app, allowing the app to open when certain links are clicked, even if the app is not currently installed on the device.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;</id><updated>2024-01-15T12:46:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Top tip - Auto Suggestion for editors</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2023/12/top-tip---auto-suggestion-for-editors/" /><id>&lt;p&gt;&lt;span&gt;Auto-suggestion can significantly enhance the efficiency, consistency, and overall quality of content created and managed by editors in a content management system. It serves as a valuable tool that supports editors in maintaining high standards and streamlining their workflow.&amp;nbsp;&lt;/span&gt;This small feature can benefit editors in many ways such as saving time by predicting and suggesting words or phrases for some fields as they type. It can promote consistency in writing style and terminology across the content. Editors will adhere to specific style guides or content standards if required for some fields.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Developers can add simple built-in auto-suggestions for editors to select when working in the edit view of Optimizely Content Management System (CMS)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Create a Custom selection class by inheriting ISelectionQuery e.g.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System;
    using System.Collections.Generic;
    using System.Linq;
    using EPiServer.ServiceLocation;
    using EPiServer.Shell.ObjectEditing;
     
      namespace EPiServer.Samples
    {
        [ServiceConfiguration(typeof(ISelectionQuery))]
        public class MySelectionQuery : ISelectionQuery
        {
            SelectItem[] _items;
            public MySelectionQuery()
            {
                _items = new SelectItem[] { 
                    new SelectItem() { Text = String.Empty, Value = String.Empty },
                    new SelectItem() { Text = &quot;Alternative1&quot;, Value = &quot;1&quot; },
                    new SelectItem() { Text = &quot;Alternative 2&quot;, Value = &quot;2&quot; } };
            }
           //Will be called when the editor types something in the selection editor.
            public IEnumerable&amp;lt;ISelectItem&amp;gt; GetItems(string query)
            {
                return _items.Where(i =&amp;gt; i.Text.StartsWith(query, StringComparison.OrdinalIgnoreCase));
            }
           //Will be called when initializing an editor with an existing value to get the corresponding text representation.
            public ISelectItem GetItemByValue(string value)
            {
                return _items.FirstOrDefault(i =&amp;gt; i.Value.Equals(value));
            }
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the &lt;strong&gt;AutoSuggestionEditor&lt;/strong&gt; attribute with your properties as below and set the &lt;strong&gt;AllowCustomValues&lt;/strong&gt; property to true so that the editor is not forced to select one of the suggested choices. By default, this property is set to false and the editor must select one of the suggested values.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[AutoSuggestSelection(typeof(MySelectionQuery))]
public virtual string SelectionEditor1 { get; set; }
    
[AutoSuggestSelection(typeof(MySelectionQuery), AllowCustomValues = true)]
public virtual string SelectionEditor2 { get; set; }&lt;/code&gt;&lt;/pre&gt;</id><updated>2023-12-28T11:22:21.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Top tip - Health Checks</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2023/12/top-tip---health-checks/" /><id>&lt;p&gt;Whether your site is a DXP or an Azure-hosted site, you may need to determine the &lt;span&gt;state of your application as if it&#39;s healthy or unhealthy. EPiServer.Cms.HealthCheck will provide you an endpoint as /epi/health, The Blog (&lt;a href=&quot;/link/e7fd6d67f00e484d94be75b644c597be.aspx&quot;&gt;https://world.optimizely.com/blogs/scott-reed/dates/2023/3/optimizely-dxp-health-checks-and-creating-custom-checks/&lt;/a&gt;) by Scott Reed explains this setup for CMS 12 in detail. It doesn&#39;t limit us to service health only, Service can be extended for many other scenarios such as listing the vulnerabilities, and checking up on some configurations or DB table sizes. The blog is a bit old but still worth reading (&lt;a href=&quot;https://www.codeart.dk/blog/2021/5/new-project-optimizely-episerver-health-checker/&quot;&gt;https://www.codeart.dk/blog/2021/5/new-project-optimizely-episerver-health-checker/&lt;/a&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&quot;love what you do&quot;&lt;/span&gt;&lt;/p&gt;</id><updated>2023-12-26T14:28:06.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Monolith, JAMStack, SPA, or Composable, Optimizely CMS is the best fit</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2023/10/monolith-jamstack-spa-or-composable-optimizely-cms-is-a-best-fit/" /><id>&lt;p&gt;Each website architecture has its own benefits and challenges.&lt;/p&gt;
&lt;p&gt;Monolith is a traditional and proven architecture to deliver web apps, combining FE and BE.&lt;/p&gt;
&lt;p&gt;To craft a JAMStack site, you employ static-site generation tools such as NextJS or Gatsby. These tools transform your website into HTML during the building process, thus introducing a game-changing shift as pages are constructed at a separate juncture.&lt;/p&gt;
&lt;p&gt;JAMStack is often confused with SPA, but there are a few fundamental differences. A Single Page Application (SPA) is constructed directly within a user&#39;s browser. When a visitor requests a page, the markup and JavaScript are transmitted to the user&#39;s browser, and the webpage is dynamically assembled in real time.&lt;/p&gt;
&lt;p&gt;Composable architecture focuses on Infrastructure as code, infrastructure automation, multi-cloud strategy, and portfolio rationalization.&lt;/p&gt;
&lt;p&gt;Optimizely does not drive the architecture anymore but gives the flexibility to adopt any architecture that suits best to business for all of your content requirements.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.ibb.co/Sy4p6fB/architecture.jpg&quot; width=&quot;661&quot; alt=&quot;Options&quot; height=&quot;263&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SAS Core was introduced on Opticon San Deigo 2023 along with many other exciting enhancements and will be available in early 2024, PAS Core is the CMS that we know to date, We can get content from any source other than the CMS also&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Optimizely Graph (Semantic and flexible search) converts your content into a graph structure. Just as search engines crawl the web to construct graph-based content indices, Optimizely Graph reshapes your CMS content for easy querying. It allows you to explore and manipulate your content using the GraphQL standard&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Builder is a visual editor&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Single source for all of your content needs, consume content anywhere&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Content will remain available, even if CMS goes down&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;PAS/Head solution will be available with or without the Optimizely graph&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</id><updated>2023-10-14T17:44:53.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Considerations before you decide to use Content Definition API</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2022/12/considerations-before-you-decide-to-use-content-definition-api/" /><id>&lt;p&gt;With the introduction of Content Definition API, it became possible to keep the definitions of the content structures, entirely in Front End and design a true headless solution with complete separation of the back end and front end. We can manage types via API and create new types as blocks and pages even without a release of the backend and create strongly typed typescript objects depending on the solution. Before you decide whether the use of Content Definition API is the right solution for you or not, you will need to consider the following points.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example projects such as &lt;a href=&quot;https://github.com/episerver/content-delivery-js-sdk&quot;&gt;https://github.com/episerver/content-delivery-js-sdk&lt;/a&gt; rely on a single big manifest.json to define all the types. To achieve strongly typed objects, you will still need extra development efforts, there could be different approaches to achieve this, e.g. &lt;a href=&quot;https://github.com/episerver/Foundation-spa-react/tree/Cms12/&quot;&gt;https://github.com/episerver/Foundation-spa-react/tree/Cms12/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If you are writing a solution for DXP and considering Content Definition API just for the sake of achieving strongly typed objects, then an alternative approach could be to use Content Graph &lt;a href=&quot;/link/2aefcdfa9169413db278877740df254a.aspx&quot;&gt;https://world.optimizely.com/blogs/Jonas-Bergqvist/Dates/2022/9/strongly-typed-cms-content-with-typescript--react3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Types generated via Content Definition API are of Types from DB, the feature available for CMS Editor for Types from code will not be available.&lt;/li&gt;
&lt;li&gt;There is no replacement available for some .Net attributes such as AllowedTypes (e.g. to restrict ContentArea for specific blocks)&lt;/li&gt;
&lt;li&gt;All settings available in the admin UI are not available through the API yet. For example, you cannot manage websites, languages, or translations.&lt;/li&gt;
&lt;li&gt;Since changes could be made to the same content types but from different sources, there may be conflicts that could affect existing content. To reduce the risk of conflicts, you should add version information to the content types. To deal with the conflicts, follow semantic versioning &lt;a href=&quot;https://docs.developers.optimizely.com/content-cloud/v1.7.0-content-definitions-api/docs/semantic-versioning&quot;&gt;https://docs.developers.optimizely.com/content-cloud/v1.7.0-content-definitions-api/docs/semantic-versioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Language Branch API is available only in version 3.4.0 or later of the Content Definitions API.&lt;/li&gt;
&lt;/ul&gt;</id><updated>2022-12-30T14:06:19.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>academy.episerver.com - SAP Litmos error</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2021/8/academy-episerver-com---sap-litmos/" /><id>&lt;p&gt;&#39;academy.episerver.com&#39; URL wasn&#39;t working for me, rather showing some confusing message about SAP Litmos... don&#39;t wait that site will come back sooner.&amp;nbsp;Just readjust bookmarks, as &#39;academy.optimizely.com&#39; is the URL to use onwards. Same credentials should work.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</id><updated>2021-08-16T07:42:24.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>ODP handy reference guide - Web SDK</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2021/6/odp-handy-reference-guide---web-sdk/" /><id>&lt;p&gt;A quick reference guide, developers might need before starting a new ODP/Zaius implementation based on &lt;a href=&quot;https://docs.developers.zaius.com/&quot;&gt;https://docs.developers.zaius.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It will be worthy to watch &lt;a href=&quot;https://www.david-tec.com/2021/05/video-adding-optimizely-data-platform-to-optimizely-commerce-cloud/&quot;&gt;https://www.david-tec.com/2021/05/video-adding-optimizely-data-platform-to-optimizely-commerce-cloud/&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;mce-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9370&quot;&gt;Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9381&quot;&gt;Batch Requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9382&quot;&gt;Consent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9383&quot;&gt;Messaging Lists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9384&quot;&gt;Customers/Profiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9385&quot;&gt;Custom event:&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mcetoc_1f8pln9386&quot;&gt;Standard events:&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2&gt;Authentication&lt;/h2&gt;
&lt;p&gt;ODP/Zaius provides two forms of authentication:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Public (Tracker ID) - is used for most API calls that send data&lt;/li&gt;
&lt;li&gt;Private - is used for querying data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keys are scoped at the account level. When you revoke a private API key, your existing key is available for 12 hours as a grace period. Public API Key and Tracker ID are synonymous.&lt;/p&gt;
&lt;h2&gt;Batch Requests&lt;/h2&gt;
&lt;p&gt;Bulk data push should be done in batch, every request can include up to 500 distinct objects. As an example, at 500 customers per request with 10 requests per second as a rate limit, you can process 5,000 customer updates per second. For higher rate limits contact support.&lt;/p&gt;
&lt;h2&gt;Consent&lt;/h2&gt;
&lt;p&gt;Consent may impact attempts to send marketing campaigns to the identifier. If noted as opted-out, certain marketing services or channels may skip the identifier, even when qualified for the campaign. Customers who have opted out cannot receive marketing messages. Only transactional messages will be received by these customers.&lt;/p&gt;
&lt;p&gt;Example:&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.consent({  consent: true,  identifier_field_name: &#39;email&#39;,  identifier_value: &#39;tyler@zaius.com&#39;,  update_reason: &#39;&#39;,  update_ts: 123456789,  event_data: {}  });&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Messaging Lists&lt;/h2&gt;
&lt;p&gt;Group customers for the purposes of tracking their communication preferences.&lt;/p&gt;
&lt;h2&gt;Customers/Profiles&lt;/h2&gt;
&lt;p&gt;To Create/Update/View Customer&amp;rsquo;s profile. Cookie with name &amp;lsquo;vuid&amp;rsquo; contains the reference to profile id.&lt;a href=&quot;https://docs.developers.zaius.com/api/rest-api/customers&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anonymize - will reset the cookie identifier associated with the browser. Use this when a user logs out or on shared devices between form submissions that include identifiers.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.customer({
    email: &quot;johnny.zaius@zaius.com&quot;
  },{
    first_name: &quot;Johnny&quot;,
    last_name: &quot;Zaius&quot;,
    gender: &quot;M&quot;
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Events&lt;/p&gt;
&lt;p&gt;Customer behaviors are tracked as events. &lt;span&gt;Events are composed of a Type(a categorical name associated with the event), Action(activity a user did within that event type), and additional metadata via fields on the event,&amp;nbsp;&lt;/span&gt; &lt;span&gt;at minimum, events require an event type and an identifier to associate the event with a customer. &lt;/span&gt;There are two types of events, custom, and standard,&lt;/p&gt;
&lt;h2&gt;Custom event:&lt;/h2&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;your_event_type_here&quot;, { 
    action: &quot;your_event_action_here&quot;,
    example_custom_field: &quot;example_value&quot;
});&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Standard events:&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;text-4505230f--TextH400-3033861f--textContentFamily-49a318e1&quot;&gt;&lt;span&gt;These are pre-defined event type/action and expected by Zaius to be accompanied with certain fields. The usage of these events makes the usage of Zaius simpler for common use cases. Zaius does not recommend or formally support Order events via the Web SDK to ensure that ad blockers do not block the purchase event. Zaius only supports sending Order refunds, returns &amp;amp; cancellations via API or CSV to ensure that ad blockers do not block these critical events. &lt;a href=&quot;https://docs.developers.zaius.com/api/&quot;&gt;https://docs.developers.zaius.com/api/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Event TYPE&lt;/td&gt;
&lt;td&gt;Activity&lt;/td&gt;
&lt;td&gt;Example&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;https://docs.developers.zaius.com/web-sdk/events/account&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;account&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;login&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;account&quot;, { action: &quot;login&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;logout&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;account&quot;, { action: &quot;logout&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;register&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;account&quot;, { action: &quot;register&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;update&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;account&quot;, { action: &quot;update&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Anonymize will reset the cookie identifier associated with the browser. Use this when a user logs out or on shared devices between form submissions that include identifiers.&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;anonymise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.anonymize();
&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Zaius will automatically parse the appropriate page path information.&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;pageview&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;pageview&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;https://docs.developers.zaius.com/web-sdk/events/navigation&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;navigation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;navigation&quot;, { 
    action: &quot;search&quot;, 
    search_term:&quot;cameras, vcr&quot;,
    category: &quot;electronics &amp;gt; consumer&quot;
});&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;sort&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;navigation&quot;, { 
    action: &quot;sort&quot;
});&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;filter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;navigation&quot;, { 
    action: &quot;filter&quot;
});&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;https://docs.developers.zaius.com/web-sdk/customers/consent&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;consent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;opt-in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.consent({
  consent: true,
  identifier_field_name: &#39;email&#39;,
  identifier_value: &#39;tyler@zaius.com&#39;,
  update_reason: &#39;&#39;,
  update_ts: 123456789,
  event_data: {}
  });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;opt-out&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.developers.zaius.com/web-sdk/events/products&quot;&gt;https://docs.developers.zaius.com/web-sdk/events/products&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;product_id is required on all events with an event type of product&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;product&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;detail&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;product&quot;, { action: &quot;detail&quot;, product_id: &quot;product-2143&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;add_to_cart&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;product&quot;, { action: &quot;add_to_cart&quot;, product_id: &quot;product-2143&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;remove_from_cart&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;product&quot;, { action: &quot;remove_from_cart&quot;, product_id: &quot;product-2143&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;add_to_wishlist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;product&quot;, { action: &quot;add_to_wishlist&quot;, product_id: &quot;product-2143&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;remove_from_wishlist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;product&quot;, { action: &quot;remove_from_wishlist&quot;, product_id: &quot;product-2143&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;https://docs.developers.zaius.com/web-sdk/events/ads&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;advertisement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;impression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;advertisement&quot;, { action: &quot;impression&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;click&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;zaius.event(&quot;advertisement&quot;, { action: &quot;click&quot; });&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;span class=&quot;text-4505230f--TextH400-3033861f--textContentFamily-49a318e1&quot;&gt;&lt;span&gt;Messaging Lists allow you to group customers for the purposes of tracking their communication preferences. For example, allowing customers to subscribe to your company newsletter or for holiday news.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;reset-3c756112--blockHint-a7403a60&quot;&gt;
&lt;p&gt;&lt;span class=&quot;text-4505230f--TextH400-3033861f--textContentFamily-49a318e1&quot;&gt;&lt;span&gt;Zaius does not require customers to be subscribed to a List to receive emails.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;subscribe&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;// subscribe johnny@zaius.com to newsletter list
zaius.subscribe({list_id: &#39;newsletter&#39;, email: &#39;johnny@zaius.com&#39;});

// unsubscribe johnny@zaius.com from newsletter list
zaius.unsubscribe({list_id: &#39;newsletter&#39;, email: &#39;johnny@zaius.com&#39;});

// subscribe johnny@zaius.com to three lists at once
zaius.subscribe({
  list_id: [&quot;newsletter&quot;, &quot;promotion&quot;, &quot;product_update&quot;], 
  email: &quot;johnny@zaius.com&quot;
});

// unsubscribe johnny@zaius.com from multiple lists at once
zaius.unsubscribe({
  list_id: [&quot;newsletter&quot;, &quot;product_update&quot;], 
  email: &quot;johnny@zaius.com&quot;
});

zaius.subscribe({
  // subscribe Johnny to all lists
  
  list_id: [&quot;newsletter&quot;, &quot;promotion&quot;, &quot;product_update&quot;],
  email: &quot;johnny@zaius.com&quot;,
  
  // update Johnny&#39;s record to include his full name
  first_name: &quot;Johnny&quot;,
  last_name: &quot;Zaius&quot;,
  
  // store information on the subscribe events
  event_custom_field: &quot;my custom value&quot;,
  custom_number_field: 123
  
});

// zaius.unsubscribe also fully supports this syntax.&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</id><updated>2021-06-22T11:06:19.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Zaius was destined to Optimizely</title><link href="https://digitalpixie.co.uk/?p=204" /><id>Optimizely(EPiServer)’s CDP journey that started from EPiServer Profile Store, destined to Optimizely Data Platform(Zaius). With the acquisition of Zaius, Optimizely (EPiServer) have a true and one of most sophisticated CDP into their product family. Partners and customers already having licenses of Visitor Intelligence should contact EPiServer/Optimizely support to know more about migrations plans. Visitor Intelligence [&amp;#8230;]</id><updated>2021-05-28T11:27:39.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Security Matters</title><link href="http://digitalpixie.co.uk/?p=125" /><id>No matter what is the size of your website, your project is handling sensitive information or it’s just a feedback form, Cyber Security matters for all. You are a novice or an expert, a developer, QA, or a solution architect, in your team. A team should have basic knowledge of cyber security. In the project [&amp;#8230;]</id><updated>2021-01-21T17:33:02.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Episerver in microservices paradigm</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2020/6/episerver-in-microservices-paradigm/" /><id>&lt;p&gt;&amp;ldquo;A microservices architecture is an approach to build a server application as a set of small services. That means a microservices architecture is mainly oriented to the back-end, although the approach is also being used for the front end. Each service runs in its own process and communicates with other processes using protocols such as HTTP/HTTPS, WebSockets, or AMQP. Each microservice implements a specific end-to-end domain or business capability within a certain context boundary, and each must be developed autonomously and be deployable independently. Finally, each microservice should own its related domain data model and domain logic and could be based on different data storage technologies (SQL, NoSQL) and different programming languages.&amp;rdquo;[1]&lt;/p&gt;
&lt;p&gt;In Microservices architecture generally, contents are also served as a service, aka CaaS. The term CaaS refers to focus on managing structured contents that some restful/web services or feed that other subscribers or applications could consume. CaaS can be referred to as an abstraction on top of a headless CMS delivered via SaaS. A headless CMS is considered a good candidate to use in a microservices architecture. Generally developing a microservice is simple but overall architecture is complex. Planning a strong architecture is a key in microservices-based architectures. Selecting the right CMS is also one of the complex questions if a business is looking for some advanced CMS with features like personalization, analytics, and AI.&lt;/p&gt;
&lt;h1&gt;Is EPiServer Headless CMS a fit in the microservice landscape?&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://i.ibb.co/MhZ6MPs/Microservices.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In EPiServer Headless, contents are served as JSON via a restful API so any programming language can consume.&lt;/li&gt;
&lt;li&gt;Provide content for native applications that are not HTML-based and Independence to integrate any new channel as we are not bounded with the CMS functionalities.&lt;/li&gt;
&lt;li&gt;It is Pluggable and configurable web API&lt;/li&gt;
&lt;li&gt;Support localized content and multi-site scenarios.&lt;/li&gt;
&lt;li&gt;Support common querying, filtering, and sorting scenarios,&amp;nbsp;able to query contents through Content Search API providing robust filtering and sorting via OData syntax&lt;/li&gt;
&lt;li&gt;Support returning access-controlled and personalized content where required.&lt;/li&gt;
&lt;li&gt;Scaleable and secure, Docker could be an option but might not be the best option to set up EpiServer Headless CMS. &quot;&lt;span&gt;Episerver chose&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/&quot;&gt;Microsoft Azure&lt;/a&gt;&lt;span&gt;&amp;nbsp;to support its Customer-Centric Digital Experience Platform, using&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/services/kubernetes-service/&quot;&gt;Azure Kubernetes Service (AKS)&lt;/a&gt;&lt;span&gt;&amp;nbsp;as the orchestration engine for high-availability multitenant microservices and&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/services/app-service/&quot;&gt;Azure App Service&lt;/a&gt;&lt;span&gt;&amp;nbsp;for easily scalable web app deployment&quot;.&amp;nbsp;&lt;/span&gt;By default supports OAuth and cookie-based authentication, However, it is allowed to customize the authorization flow and use your preferred authorization mechanism like AzureAD or GitHub.&lt;/li&gt;
&lt;li&gt;Framework agnostic features such as on Page Editing can be used with any javascript framework such as Angular, React, or Vue.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;EPiServer Headless&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/link/6ffa5cb8173a414eac25740deeafdbc8.aspx&quot;&gt;https://world.episerver.com/documentation/developer-guides/content-delivery-api/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/7ce146c1219c46cfb41062d597a23723.aspx&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Future Of EPiServer Headless&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/link/be8077bc415c4afca844daf0fb0e83bb.aspx&quot;&gt;https://world.episerver.com/blogs/martin-ottosen/dates/2019/12/asp-net-core-beta-program/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e64362f8872e492ab4f3191267c0c760.aspx&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Contextual considerations&lt;/h1&gt;
&lt;p&gt;Conceptually a microservice can be derived as a bounded context in a domain-driven design where each bounded context should have its own model and database. EPiServer CMS as a whole should be considered as a single bounded context. Content in itself can&amp;rsquo;t be divided further into microservices-based into their types (Images, Textual, or Pdfs).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;Content Considerations&lt;/h1&gt;
&lt;p&gt;In EPiServer a content item is not necessarily only a web page, it may not have an addressable URL and it may be just a container for data that can be seen as a database record. Sometimes, the same piece of content can be used on a page, on social media or in print which means the content is no longer assigned to a specific channel. Usually, those kinds of content items are simple with only basic property types and some metadata. Content Manager is available to create this kind of content.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/dbbcb8c637ae4dcc80685dd99ca3ae05.aspx&quot;&gt;https://world.episerver.com/blogs/bartosz-sekula/dates/2020/4/content-manager---lightweight-editing-ui/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/a4d4968ba9234975b52bfe6fe9719702.aspx&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/d9d8c3d5dc6249f88ad78c93cc70840c.aspx&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;SPA implementations with Headless CMS with OPE support&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;/link/77c693a1814446ffb2f76af6babbef08.aspx&quot;&gt;https://world.episerver.com/blogs/remko-jantzen/dates/2020/5/introducing-foundation-spa-react/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/episerver/musicfestival-vue-template&quot;&gt;https://github.com/episerver/musicfestival-vue-template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[1] - &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/architecture/microservices/&quot;&gt;https://docs.microsoft.com/en-us/dotnet/architecture/microservices/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/dbbcb8c637ae4dcc80685dd99ca3ae05.aspx&quot;&gt;https://world.episerver.com/blogs/bartosz-sekula/dates/2020/4/content-manager---lightweight-editing-ui/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://customers.microsoft.com/en-gb/story/786162-episerver-partner-professional-services-azure&quot;&gt;https://customers.microsoft.com/en-gb/story/786162-episerver-partner-professional-services-azure&lt;/a&gt;&lt;/p&gt;</id><updated>2020-06-02T13:42:12.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>How your site appears in google search results</title><link href="http://kkhan-episerver.blogspot.com/2020/05/how-your-site-appears-in-google-search.html" /><id>Search engines now look deep into site contents and try to understand more about your site e.g. Google uses structure data to understand more about the content on your page. By providing structured data we not only can get the benefit of special features like rich snippets but also our site will be eligible to appear in graphic search results. By providing structured data you can outstand your site presence in the google search results and in result increase in clickthrough.&lt;br /&gt;&lt;br /&gt;While searching keyword &#39;eCommerce&#39; (from the UK, 5th of May 2020) I get the following results.&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-tKZ7bjdxOv4/XrGWZO9XoqI/AAAAAAAAROg/6e5tDbHHUPQyhFy_E4ZXEqW0SXxmHPwHgCLcBGAsYHQ/s1600/ecommerce.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;859&quot; data-original-width=&quot;1345&quot; height=&quot;408&quot; src=&quot;https://1.bp.blogspot.com/-tKZ7bjdxOv4/XrGWZO9XoqI/AAAAAAAAROg/6e5tDbHHUPQyhFy_E4ZXEqW0SXxmHPwHgCLcBGAsYHQ/s640/ecommerce.JPG&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;These are the highlights of the page&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://support.google.com/websearch/answer/9351707?p=featured_snippets&quot;&gt;Featured snippet&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Related Images&lt;/li&gt;&lt;li&gt;Article&lt;/li&gt;&lt;li&gt;Books&lt;/li&gt;&lt;li&gt;People also searched for&lt;/li&gt;&lt;li&gt;FAQ&lt;br /&gt;and the rest of the search results.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Google supports structured data in the following formats&amp;nbsp;&lt;a href=&quot;http://json-ld.org/&quot;&gt;JSON-LD&lt;/a&gt;&amp;nbsp;(recommended, use this format whenever possible),&amp;nbsp;&lt;a href=&quot;https://www.w3.org/TR/microdata/&quot;&gt;Microdata&lt;/a&gt;,&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;https://rdfa.info/&quot;&gt;RDFa&lt;/a&gt;. Google also uses&amp;nbsp;&lt;a href=&quot;https://schema.org/&quot;&gt;schema.org&lt;/a&gt; vocabulary, but for definitive, google search behaviors, rely on documentation provided on&amp;nbsp;developers.google.com rather schema.org.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There can be several items in your site for which structure data can be provided, e.g. article, breadcrumb, carousel, event, FAQ, logo, organization, or product. You can find examples of JSON-LD structured data code snippets from google&amp;nbsp;&lt;a href=&quot;https://developers.google.com/search/docs/data-types/article&quot;&gt;here&lt;/a&gt;. A full list of vocabulary definition files can be downloaded from &lt;a href=&quot;https://schema.org/docs/developers.html&quot;&gt;schama.org&lt;/a&gt;.&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Implementation of structured data could be very simple to complex depending on your site and the way pages and blocks are structured in the EPiServer site, general structure data guidelines are available &lt;a href=&quot;https://developers.google.com/search/docs/guides/sd-policies&quot;&gt;here&lt;/a&gt;. A reference implementation based on the&amp;nbsp;&lt;a href=&quot;https://www.nuget.org/packages/Schema.NET/3.5.0&quot;&gt;schema.net&lt;/a&gt;&amp;nbsp;package can be found in &lt;a href=&quot;https://github.com/episerver/Foundation/tree/develop/src/Foundation.Cms/SchemaMarkup&quot;&gt;EPiServer foundation project&lt;/a&gt;. (Credits: Paul Gruffydd)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</id><updated>2020-05-06T10:06:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>How your site appears in google search results</title><link href="https://digitalpixie.co.uk/how-your-site-appears-in-google-search-results" /><id>Search engines now look deep into site contents and try to understand more about your site e.g. Google uses structure data to understand more about the content on your page. By providing structured data we not only can get the benefit of special features like rich snippets but also our site will be eligible to [&amp;#8230;]</id><updated>2020-05-06T10:06:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Will your site be effected in Chrome 80</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2020/2/will-your-site-be-effected-with-chrome-80/" /><id>&lt;p&gt;Chrome 80 will treat cookies as SameSite=Lax by default if no SameSite attribute is specified and will reject insecure SameSite=None cookies.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromestatus.com/feature/5088147346030592&quot;&gt;https://www.chromestatus.com/feature/5088147346030592&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromestatus.com/feature/5633521622188032&quot;&gt;https://www.chromestatus.com/feature/5633521622188032&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Out of the box EPi Server&#39;s CMS website functionality isn&#39;t effected, but it might be effecting other areas of your website. e.g.&lt;/p&gt;
&lt;p&gt;your integrations with Identity Providers using protocols such as SAML 2.0 or OpenID Connect or&amp;nbsp; analytics cookies that your web application creating as a third-party cookie or any feature depending on third party dependent cookies or if you are querying APIs from a third-party domain.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromestatus.com/features/schedule&quot;&gt;https://www.chromestatus.com/features/schedule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/a182c387633d45cda9e39c6a1aafc035.aspx&quot;&gt;https://world.episerver.com/forum/developer-forum/-Episerver-75-CMS/Thread-Container/2020/1/upcoming-samesite-cookie-changes-and-episerver/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://auth0.com/blog/browser-behavior-changes-what-developers-need-to-know/&quot;&gt;https://auth0.com/blog/browser-behavior-changes-what-developers-need-to-know/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/&quot;&gt;https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chromium.org/updates/same-site&quot;&gt;https://www.chromium.org/updates/same-site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.seerinteractive.com/blog/samesite-security-update-chrome/&quot;&gt;https://www.seerinteractive.com/blog/samesite-security-update-chrome/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webkit.org/blog/8828/intelligent-tracking-prevention-2-2/&quot;&gt;https://webkit.org/blog/8828/intelligent-tracking-prevention-2-2/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google announced it would end support for third-party cookies in Chrome by 2022&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html&quot;&gt;https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marketingland.com/marketers-respond-to-google-chrome-cookie-decision-with-mixture-of-hope-and-fear-274792&quot;&gt;https://marketingland.com/marketers-respond-to-google-chrome-cookie-decision-with-mixture-of-hope-and-fear-274792&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</id><updated>2020-02-03T19:56:24.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Use of strategy pattern to change page behaviour</title><link href="https://world.optimizely.com/blogs/K-Khan-/Dates/2020/1/use-of-strategy-pattern-to-change-page-behaviour/" /><id>&lt;p&gt;There are scenarios where we have to change our page behavior or algorithms at run time based on Epi Configurations. Generally, a developer approaches with if-else statements to deal with this by compromising design principals. We can get help from the Strategy Pattern to adhere to SOLID principals. Below is an Illustrations for a fake scenario to demonstrate implementation where editors will set a recipe filter to change the results of the page or selecting the right dataset for the page.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.ibb.co/kJKJCCZ/strategy.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;EPiServer Page and configurations&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public enum LayoutType
    {
        Diabitic,
        HighProtein,
        LowFat,
        HighFibre
    }

    /// &amp;lt;summary&amp;gt;
    /// Create an interface for configuration
    /// &amp;lt;/summary&amp;gt;
    public interface IStrategyConfiguration
    {
        LayoutType LayoutType { get; set; }
    }

    /// &amp;lt;summary&amp;gt;
    /// Implement Configuration in your page or block
    /// &amp;lt;/summary&amp;gt;
    public class RecipeLandingPage : PageData, IStrategyConfiguration
    {
        [Display(GroupName = SystemTabNames.Settings, Name = &quot;Layout&quot;, Description = &quot;Select page layout&quot;)]
        public LayoutType LayoutType { get; set; }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PageController/factory where we need to change the algorithm at runtime.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
    /// Page Controller
    /// &amp;lt;/summary&amp;gt;
    public class RecipeLandingPageController : PageController&amp;lt;RecipeLandingPage&amp;gt;
    {
        /// &amp;lt;summary&amp;gt;
        /// IRecipeFilterSelector is a resolver that will select right IRecipeFilter for us
        /// &amp;lt;/summary&amp;gt;
        private readonly IRecipeFilterSelector _recipeFilterSelector;

        public RecipeLandingPageController(IRecipeFilterSelector recipeFilterSelector)
        {
            _recipeFilterSelector = recipeFilterSelector;
        }

        public async Task&amp;lt;ActionResult&amp;gt; Index(RecipeLandingPage currentPage)
        {
            //Select a filter based on epi configurations
            var filter = _recipeFilterSelector.GetRecipeFilter(currentPage.LayoutType);
            var pageModel = YourPageModel(currentPage);
            pageModel.Advertisements = filter.GetAdvertisements();
            pageModel.Suggestions = filter.GetSuggestions();
            return View(model);
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need&amp;nbsp;IRecipeFilterSelector that could return us correct&amp;nbsp;IRecipeFilter.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    /// &amp;lt;summary&amp;gt;
    /// will resolve correct IRecipeFilter
    /// &amp;lt;/summary&amp;gt;
    public interface IRecipeFilterSelector
    {
        IRecipeFilter GetRecipeFilter(LayoutType layoutType);
    }

    /// &amp;lt;summary&amp;gt;
    /// Select IRecipeFilter based on EPiCongigurations
    /// &amp;lt;/summary&amp;gt;
    public class RecipeFilterSelector : IRecipeFilterSelector
    {
        private readonly IEnumerable&amp;lt;IRecipeFilter&amp;gt; _recipeFilters;
        // structuremap will push all implementations of IRecipeFilter
        public RecipeFilterSelector(IEnumerable&amp;lt;IRecipeFilter&amp;gt; recipeFilters)
        {
            _recipeFilters = recipeFilters;
        }

        public IRecipeFilter GetRecipeFilter(LayoutType layoutType)
        {
            return _recipeFilters.FirstOrDefault(x =&amp;gt; x.LayoutType == layoutType);
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need separate implementations for IRecipeFilter&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
    /// Main service
    /// &amp;lt;/summary&amp;gt;
    public interface IRecipeFilter
    {
        LayoutType LayoutType { get; }
        IList&amp;lt;Advertisement&amp;gt; GetAdvertisements();
        IList&amp;lt;Suggestion&amp;gt; GetSuggestions();
    }

    /// &amp;lt;summary&amp;gt;
    /// Separation of concerns achieved, implementation for specific scenarios
    /// &amp;lt;/summary&amp;gt;
    public class DiabiticRecipeFilter : IRecipeFilter
    {
        public LayoutType LayoutType =&amp;gt; LayoutType.Diabitic;

        public IList&amp;lt;Advertisement&amp;gt; GetAdvertisements()
        {
            throw new NotImplementedException();
        }

        public IList&amp;lt;Suggestion&amp;gt; GetSuggestions()
        {
            throw new NotImplementedException();
        }
    }
    /// &amp;lt;summary&amp;gt;
    /// Separation of concerns achieved, implementation for specific scenarios
    /// &amp;lt;/summary&amp;gt;

    public class HighProteinRecipeFilter : IRecipeFilter
    {
        public LayoutType LayoutType =&amp;gt; LayoutType.HighProtein;

        public IList&amp;lt;Advertisement&amp;gt; GetAdvertisements()
        {
            throw new NotImplementedException();
        }

        public IList&amp;lt;Suggestion&amp;gt; GetSuggestions()
        {
            throw new NotImplementedException();
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Join these pieces in structuremap to work together&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//Collect all implementations of IRecipeFilter
    c.Scan(s =&amp;gt;
    {
    s.AssemblyContainingType(typeof(IRecipeFilter));
    s.AddAllTypesOf(typeof(IRecipeFilter));
    });
    //pass this to selector
    c.For&amp;lt;IRecipeFilterSelector&amp;gt;().Use&amp;lt;RecipeFilterSelector&amp;gt;().Singleton();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://i.ibb.co/wp1nYbs/final.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Be SOLID in the new year! Happy new year!&lt;/p&gt;</id><updated>2020-01-01T16:32:05.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>