For Optimizely and .NET teams

Optimizely CMS, DXP, AI editor tools, and technical SEO

Practical solutions, open-source tools, and field-tested code to help you solve real Optimizely challenges and ship with confidence.

Latest posts

All posts →

Tuesday, 21 July 2026

Advanced Task Manager Gets a Big Update for Optimizely CMS

Optimizely's content approval workflow works well when you are approving one item at a time. The problem starts when you are managing a large queue across pages, blocks, and media. Once the list grows, finding the right items, approving them in bulk, or publishing them in a controlled way becomes much more time-consuming than it should be.

This update focuses on solving those real editorial workflow problems. Every feature below came from day-to-day use of the tool in larger Optimizely solutions where too many clicks, too much scrolling, or missing workflow controls were slowing editors down.

Related posts: CMS 12 release post | Legacy CMS 11 post

Advanced filtering

The task list now includes a proper filter bar, making it easier to work with larger approval queues.

  • Status - switch between In Review and Ready to Publish.
  • Type - filter Pages, Blocks, or Assets/Media.
  • Site - narrow the list to one site in multi-site solutions.
  • Content search - search by content ID or part of the content name.

Each filter updates the URL, so filtered views can be bookmarked or shared with other editors.

Note: Active filters appear as removable badges below the filter bar, and a Clear all option removes everything at once.

Select all across pages

The existing table checkbox used to select only the current page of results. This update adds support for selecting all matching items across all pages.

If more results exist than are visible on the current page, a banner appears and lets the editor load every matching approval ID into the current selection. That means bulk approval can now cover the full filtered result set in one action.

This selection respects the active filters, so editors can safely approve only the tasks they intended to include.

Scheduled publishing

Publishing immediately after approval is still supported, but it is no longer the only option.

When Publish selected content after approval is enabled, editors can now choose to schedule publishing for a specific future date and time. The selected datetime is passed into Optimizely's normal publishing pipeline using IVersionable.StartPublish, so standard scheduled publishing behavior is used without any custom publishing job.

Approve blocks and media used by a page

This is one of the most useful additions in the release.

Sometimes a page is ready to go live, but the blocks or media it references are still waiting in their own approval queues. Instead of finding those items one by one, editors can now use Approve Page Dependencies to approve pending block and media dependencies for a selected page in one action.

  1. Open Approve Page Dependencies from the filter bar.
  2. Select a page from the hierarchy tree, or enter the content ID directly.
  3. Choose one or more language branches.
  4. Optionally enter an approval comment.
  5. Optionally publish approved dependencies immediately.
  6. Run the action and review the result count.

Behind the scenes, the tool inspects ContentArea and ContentReference properties on the selected page, gathers referenced blocks and media, and approves the items that still have pending approval steps.

Note: This action approves only the dependencies referenced by the page. It does not approve the page itself.

Task ordering

The task list columns are now sortable. Editors can sort by content name, content type, task type, submission date, who started the review, or deadline if the deadline property is enabled.

This sounds small, but it makes a big difference when triaging long queues and trying to prioritize urgent work.

Site column for multi-site solutions

In multi-site installations, the list now includes a Site column so editors can immediately see which site each task belongs to. In single-site environments, the column stays hidden.

This works especially well with the Site filter when approval queues need to be reviewed site by site.

Version availability

As of July 24, 2026, these features are available in:

  • Version 4.1.0 for Optimizely CMS 13 / .NET 10
  • Version 3.1.0 for the CMS 12 branch

Change Approval support is currently available only in the CMS 12 branch, because EPiServer.ChangeApproval does not yet have a CMS 13-compatible release.

Install or update

dotnet add package AdvancedTaskManager

Links

GitHub repository
NuGet package

Conclusion

This release makes Advanced Task Manager much more useful for teams handling larger approval volumes across pages, blocks, media, sites, and languages. The focus here is less about adding features for their own sake and more about making approval workflows faster, clearer, and easier to control in real Optimizely projects.

If you run into issues or want to suggest further improvements, the source code, changelog, and issue tracker are available on GitHub.

July 21, 2026

Friday, 10 July 2026

Optimizely DXP: Every Supported Culture, One Searchable Page

Quick one for anyone building multi-language sites on Optimizely DXP. I put together a reference tool listing all 806 supported cultures. More usefully, it shows which ones actually work with Azure Translator's 1-click auto-translate, and which get full NLP treatment (stemming, tokenization, decompounding) from Optimizely Graph.

If you've ever added a new market and then spent twenty minutes digging through docs to figure out whether editors will get auto-translate for that locale, or whether search will actually work well in that language, this is for that exact moment. Search or filter by culture name or code, grab the exact culture code you need for config, and see right away which capabilities you're getting.

806 cultures. 33 with Azure Translator support. Full Graph NLP coverage mapped out. All in one table.

Check it out here: Optimizely DXP – Supported Cultures / Languages

July 10, 2026

Tuesday, 3 March 2026

OpenAI-Driven AI Assistant for TinyMCE in Optimizely CMS 12

The Tiny.AI add-on enhances Optimizely CMS 12 by seamlessly integrating OpenAI directly into the TinyMCE editor. It empowers editors to rewrite, improve, summarize, expand, or translate selected content without leaving the CMS. Instead of copying content into external AI tools and risking formatting issues, Tiny.AI processes HTML safely and returns clean, CMS-ready output.

Installation

The command below will install the add-on in your Optimizely project.

dotnet add package A2Z.Optimizely.Tiny.AI

Configuration

Add your OpenAI configuration inside appsettings.json. The model value below is an example and can be updated to a supported model that fits your setup.

{
  "OpenAI": {
    "ApiKey": "YOUR_API_KEY",
    "Model": "gpt-4o-mini"
  }
}

The module automatically registers required services, the API controller, and the TinyMCE plugin.

Service Registration

The package registers the OpenAI service, circuit breaker, and authorization services automatically through an initialization module.

[ModuleDependency(typeof(InitializationModule))]
public class AiInitialization : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        context.Services.AddHttpClient<IOpenAiService, OpenAiService>();
        context.Services.AddSingleton<EditorAuthorizationService>();
        context.Services.AddSingleton<SimpleCircuitBreaker>();
    }
}

Usage

Once installed and configured, editors will see a new AI Assistant button inside the TinyMCE toolbar.

TinyAI Icon

How it works:

  1. Select content inside the TinyMCE editor.
  2. Click the AI Assistant button.

  3. Choose an action (Rewrite, Improve, Summarize, Expand, Translate).

  4. Optionally specify a language.
  5. Apply changes and the HTML is replaced instantly.

The AI processes the selected HTML and returns valid HTML only, preserving links and formatting.

Security

Access to Tiny.AI is restricted to users in the following roles:

  • CmsEditors
  • Administrators

Authorization is validated server-side to ensure only permitted users can invoke AI functionality.

Resilience & Performance

Tiny.AI is built for production environments and includes:

  • Retry logic for transient API failures
  • Exponential backoff for rate limiting (429 responses)
  • Circuit breaker protection after repeated failures
  • Structured logging for monitoring
  • Token usage tracking
  • Estimated cost calculation per request

If multiple consecutive failures occur, the circuit breaker temporarily disables AI calls to protect system stability.

Cost Transparency

Each request returns:

  • Prompt tokens
  • Completion tokens
  • Total tokens
  • Estimated cost

This provides visibility into AI usage and allows teams to monitor spending effectively.

API Endpoint

POST /api/editor/ai/action

Example request:

{
  "action": "rewrite",
  "html": "<p>Some content</p>",
  "language": "en"
}

Example response:

{
  "html": "<p>Rewritten content...</p>",
  "tokens": 512,
  "cost": 0.0003
}

Compatibility

Tiny.AI currently supports Optimizely CMS 12 only. Check the GitHub repository or package page for the latest updates and version support.

Why Tiny.AI?

AI is becoming an essential productivity tool for content teams. Tiny.AI integrates OpenAI directly into Optimizely CMS workflows while maintaining security, HTML integrity, and operational resilience.

It eliminates the need for external tools and keeps the editorial workflow fast, clean, and fully integrated.

You can access the code and documentation for Tiny.AI on its GitHub repository.

March 03, 2026

Thursday, 12 February 2026

Advanced Form Submissions for Optimizely CMS

Advanced Form Submissions is an alternative submissions dashboard for Optimizely CMS 12 built for teams that need better control over Optimizely Forms data. It improves the default submission view with stronger filtering, export tools, bulk actions, and a more practical review experience for editors and administrators.

In larger Optimizely solutions, form data quickly becomes harder to manage across multiple sites, languages, and forms. This add-on gives teams a faster and more flexible way to review submissions without relying on the default interface alone.

Why use Advanced Form Submissions

  • Filter submissions by site, language, and form.
  • Search across submission content and apply date range filters.
  • Export filtered data as CSV, XML, or JSON.
  • Delete submissions more efficiently.
  • Open the original form directly from the dashboard.
  • Preview a submission on the original page with form hydration.

Key features

Personalized dashboard

The dashboard is designed for day-to-day editorial use and supports a more flexible review workflow.

  • Reorder columns to fit your needs.
  • Hide fields that are not useful for your review process.
  • Save settings per user, form, and language.
  • Use paged data loading for better performance on large datasets.

Advanced filtering and search

Submissions can be narrowed down quickly with filters for site, language, and form, plus free-text search and from/to date filtering.

Export and management tools

  • Export filtered submissions as CSV, XML, or JSON.
  • Delete selected or filtered submissions.
  • Jump directly to the related Form Container Block in CMS.

Better data display

  • File upload values are shown as clickable links.
  • Selection fields such as checkboxes, radio buttons, and dropdowns are rendered more clearly during review.

Quick view of an Optimizely form submission in Advanced Form Submissions

View submission on page

The add-on supports form hydration, which lets authorized users open a submitted form directly on the original page with the submitted values prefilled.

  • Open a submission in its original page context.
  • Review how the form looked when it was submitted.
  • Keep the workflow permission-aware and security-aware.

Advanced Form Submissions dashboard in Optimizely CMS

Advanced Form Submissions access from the Optimizely CMS form block

How to access it

The dashboard is available in two ways:

  • From the CMS global menu as Form Submissions.
  • From a Form Container Block through the custom Advanced Form Submissions view.

Installation

Install the package from the Optimizely NuGet feed:

dotnet add package A2Z.Optimizely.AdvancedFormSubmissions

Register the add-on during application startup:

using AdvancedFormSubmissions;

builder.Services.AddAdvancedFormSubmissions();

This registration adds the module, protected resources, CMS integration, and the default authorization policy.

Authorization and security

The add-on uses a dedicated authorization policy: form:submissions.

By default, access is granted to:

  • CmsAdmins
  • WebAdmins
  • Administrators

The same policy protects menu visibility, dashboard access, and form hydration behavior.

Compatibility

As of July 24, 2026, this add-on supports Optimizely CMS 12.

Limitations

Encrypted Optimizely Forms fields are intentionally not supported for dashboard display or hydration.

  • Encrypted values cannot be read through public APIs.
  • Encrypted fields are not hydrated on the front end.
  • Exports may show empty or masked values for encrypted fields.

Links

GitHub repository
README
NuGet package

FAQ

Does this replace Optimizely Forms?
No. It improves how submissions are reviewed and managed after forms are submitted.

Can editors preview submissions on the original page?
Yes. Authorized users can use form hydration to open a submitted form in its original page context.

Does it support encrypted fields?
No. Encrypted fields are intentionally excluded from hydration and display.

February 12, 2026

Wednesday, 24 September 2025

Master Language Switcher for Optimizely CMS

Master Language Switcher is an admin tool for Optimizely CMS 12 and 13 that helps teams change the master language of multilingual content more safely. It is designed for cases where you need to promote an existing language branch or convert the current master language to a new target language without manually working through content item by item.

For multilingual Optimizely solutions, this can save a significant amount of time and reduce the risk of mistakes when working across large content trees.

Why use Master Language Switcher

  • Switch - If the target language branch already exists, it becomes the new master language.
  • Convert - If the target branch does not exist, the current master language is converted and promoted to the target language.
  • Batch processing - Large content trees are processed in smaller batches for more controlled execution.
  • Clear feedback - Editors and administrators can review item-by-item results directly in the UI.

Supported content types

The tool can process the following content:

  • Pages - The selected root page and, optionally, its descendants.
  • Blocks - Blocks used inside page content areas.
  • Media - Media items when selected as the root or included through recursive hierarchy processing.

Important considerations

Important:
  • This tool updates content at database level and bypasses normal CMS editing safeguards.
  • Large operations may cause timeouts or database locks.
  • Run it during off-peak hours and always take a database backup first.
  • If changes do not appear immediately, clear any CDN or application cache and restart the site if needed.
  • If you use Optimizely Search & Navigation, reindex the content after the operation so search reflects the new master language.

Installation

Install the package from the Optimizely NuGet feed with:

dotnet add package A2Z.Optimizely.MasterLanguageSwitcher

How to use it

  1. Go to Admin > Tools > Master Language Switcher.
  2. Select the page or content root you want to process.
  3. Choose the target language.
  4. Optionally enable recursive processing to include child content.
  5. Click Change Language and review the live results in the UI.

Result feedback

The tool shows a clear results table after execution:

  • Each page, block, and media item is listed with its action and status.
  • Rows make it easier to spot switched, converted, skipped, or failed items.
  • A summary section shows totals for each result type.

Compatibility

This tool supports Optimizely CMS 12 and CMS 13. Check the package page and GitHub repository for the latest version details and updates.

Links

GitHub repository
NuGet package

FAQ

What is the difference between switch and convert?
Switch promotes an existing target language branch to master. Convert changes the current master language to the selected target language when that target branch does not already exist.

Is this safe for large trees?
It is designed to handle larger operations in batches, but you should still run it carefully, during quieter periods, and only after taking a backup.

Do I need to reindex after running it?
Yes, if you use Optimizely Search & Navigation, reindexing is recommended after the master language changes.

September 24, 2025

Wednesday, 17 September 2025

How to Allow AI Bots in Your robots.txt File (2025 Edition)

The world of AI is moving fast and so are the bots that crawl the web to feed large language models (LLMs), AI search engines, and generative tools. If you want your site’s content to be available for AI models like ChatGPT, Claude, Perplexity, or Gemini, you can explicitly grant permission by updating your robots.txt file.

In this guide, you’ll learn:

  • Why AI bots matter in 2025
  • Which user-agents to include
  • A ready-to-use robots.txt template

Why AI Bots Need robots.txt Rules

Traditionally, robots.txt controlled search engines like Googlebot and Bingbot. Now, AI companies also respect these directives to decide whether your content can be indexed for AI search or used for model training.

  • Search bots (AI answers/assistants): Allowing them means your content may appear in AI-powered search results (e.g., Perplexity, You.com).
  • Training crawlers: Allowing them means your content may be used to train or fine-tune large AI models (e.g., GPTBot, ClaudeBot).

By updating your robots.txt, you can allow, block, or mix your policies across these bots.


Major AI User-Agents in 2025

OpenAI (ChatGPT / SearchGPT)

  • GPTBot => training crawler
  • ChatGPT-User => on-demand browsing in ChatGPT
  • OAI-SearchBot => indexing for SearchGPT

Anthropic (Claude)

  • ClaudeBot => model training
  • Claude-Web / anthropic-ai => crawling/AI access

Perplexity

  • PerplexityBot => AI search engine

Google (Gemini)

  • Google-Extended => controls if Gemini can use your content for AI

Apple

  • Applebot-Extended => controls Apple AI training usage

Amazon

  • Amazonbot => AI + product/search crawling

Common Crawl

  • CCBot => feeds public datasets used in AI training

AI Search Engines

  • YouBot => You.com
  • PhindBot => Phind AI search
  • ExaBot => Exa.ai
  • AndiBot => Andi search
  • FirecrawlAgent => Firecrawl AI

Example: Allowing AI Bots

Here’s a robots.txt example that explicitly allows AI bots alongside traditional crawlers:

# Default: allow all crawlers
User-agent: *
Disallow:

# --- Explicitly ALLOW major AI/LLM bots ---

# OpenAI
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
User-agent: OAI-SearchBot
Allow: /

# Anthropic (Claude)
User-agent: ClaudeBot
Allow: /
User-agent: Claude-Web
Allow: /
User-agent: anthropic-ai
Allow: /

# Perplexity
User-agent: PerplexityBot
Allow: /

# Google AI usage token
User-agent: Google-Extended
Allow: /

# Apple AI usage token
User-agent: Applebot-Extended
Allow: /

# Amazon
User-agent: Amazonbot
Allow: /

# Common Crawl
User-agent: CCBot
Allow: /

# AI search engines
User-agent: YouBot
Allow: /
User-agent: PhindBot
Allow: /
User-agent: ExaBot
Allow: /
User-agent: AndiBot
Allow: /
User-agent: FirecrawlAgent
Allow: /

Optional: Balanced Policy (Allow AI Search, Block Training)

If you want to appear in AI search results but not have your content used for model training, use a mixed policy. For example:

# Allow AI search crawlers
User-agent: PerplexityBot
Allow: /
User-agent: YouBot
Allow: /
User-agent: PhindBot
Allow: /
User-agent: ExaBot
Allow: /
User-agent: AndiBot
Allow: /
User-agent: OAI-SearchBot
Allow: /

# Disallow training/aggregator crawlers
User-agent: GPTBot
Disallow: /
User-agent: ClaudeBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: Applebot-Extended
Disallow: /
User-agent: CCBot
Disallow: /

Pro Tips

  • Keep it updated: New AI bots appear frequently so review your list quarterly.
  • Combine with enforcement: Some bots may ignore rules. If strict compliance matters, pair robots rules with IP/reverse-DNS checks or WAF bot controls.
  • Test quickly: Host your robots.txt at https://<your-domain>/robots.txt and fetch it from a browser or with curl to verify.

Going Further with SEO

If you’re running an Optimizely CMS site and want deeper control over SEO, check out my open-source tool: SEOBOOST for Optimizely CMS.

AI is becoming a parallel discovery channel next to Google. Your robots.txt file is the simplest way to take control of how your content participates.

September 17, 2025

Thursday, 4 September 2025

How to Preview Unpublished Content on the Frontend in Optimizely CMS 12

Introduction

In my previous post, I explained how to customize the ContentArea rendering pipeline in Optimizely CMS 12 so editors can see unpublished block content while previewing pages in the CMS.

That approach works great inside the CMS UI (Edit/Preview mode). But what if you want to enable the same functionality on the front-end site, using a simple query string flag?

That’s where the ?showdrafts=true parameter comes in.

The Problem

By default, Optimizely only shows published content when you browse a site page directly. Even if a page has a saved draft version (with new or updated blocks), you won’t see it on the public site unless the draft is published.

  • The page instance returned by routing is the published version.
  • The ContentAreaRenderer filters unpublished items before rendering.

As a result, any unpublished blocks in a draft page are invisible.

The Approach

We need three things working together:

  1. Detect ?showdrafts=true.
  2. Load the draft page version instead of the published one.
  3. Render all ContentArea items (published + unpublished) so draft blocks are not filtered out.

Step 1: Helper to Fetch Draft Pages


Step 2: Ensure Draft Blocks Render Too


Override ContentAreaRenderer to skip the internal filtering step when showdrafts=true.

Step 3: Controller Example


Final Result

  • Default URL /about-us → shows published page + published blocks.
  • With ?showdrafts=true → loads the draft page (so unpublished block references are included) and renders them.
  • Works consistently both inside CMS preview and on the public site (for editors/admins).

Closing Thoughts

The ?showdrafts=true query parameter is a simple but powerful way to let editors verify draft content directly on the site without switching to CMS preview.

When combined with the approach from my earlier post, you now have full control over showing unpublished content both inside and outside the CMS interface.

Just remember: never expose drafts to anonymous visitors — always enforce role checks.

September 04, 2025