Sending email with customized email body using Sitecore forms

Did you work on a requirement to send email to your partners/visitors in Sitecore? yeah… I know that’s a pretty common requirement right? we can create custom forms and send emails or even a better solution is to leverage Sitecore forms and use/create actions to send emails.

In Sitecore we can use available Send Email Submit Action to send the email, In the below screen shot we can see the available option to configure the Send Email action for Submit button.

So far so good, now let’s take an example where we want to send an email with the customized message body, how to go there? We have solution like using MailMessage class and setting message properties like Subject, Body, from address etc.. and then create SMTP client to send email.

We can also leverage SendEmail submit action and update the message body to send custom data, this would be useful for such requirements like where we want to send some activation link, data to our end users for confirmation.

Let’s see how we can use second option and send customized message body.

Here are the steps required:

  • Create a class and inherit that class with Sitecore Forms SubmitActions SendEmail class.
public class SendCustomEmail : Sitecore.ExperienceForms.Mvc.Processing.SubmitActions.SendEmail
  • Initialize a new instance of the class you created above.
public SendCustomEmail (ISubmitActionData submitActionData)  : base(submitActionData)
  • Next step is to override Execute method with SendEmailData/FormSubmitContext parameters, set the SendEmaiData Body property using custom value and perform other business rule(s) as per project/business requirements.
protected override bool Execute(SendEmailData data, FormSubmitContext formSubmitContext)
            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));

            if (!formSubmitContext.HasErrors)
                // Process formSubmitContext here...
                var emailBody = "Custom Email Message"; // Set custom email body message here...
                data.Body = data.Body.Replace("#email#", emailBody);

            return true;
  • In the above step we have set the Body property of SendEmailData class and replaced that value with a placeholder text which is set as part of Sitecore form we created.
  • Next step is to call base class Execute method and you are done.
base.Execute(data, formSubmitContext);
  • After this we need to create a new submit action in Sitecore and configure the required fields like Model Type, Error Message and Editor.
  • Once this is done you just need to select the newly created submit action as part of the Submit button and you are good to go.

Here is the full code for ref.

// <copyright file="SendCustomEmail.cs" company="Sandbox">
// Copyright (c) Sandbox. All rights reserved.
// </copyright>

namespace Sandbox.Feature.Actions
    using Sitecore.Diagnostics;
    using Sitecore.ExperienceForms.Models;
    using Sitecore.ExperienceForms.Mvc.Models.SubmitActions;
    using Sitecore.ExperienceForms.Processing;

    public class SendCustomEmail : Sitecore.ExperienceForms.Mvc.Processing.SubmitActions.SendEmail
        /// <summary>
        /// Initializes a new instance of the <see cref="SendCustomEmail"/> class.
        /// </summary>
        /// <param name="submitActionData">submitActionData.</param>
        public SendCustomEmail(ISubmitActionData submitActionData)
            : base(submitActionData)

        /// <summary>
        /// Executes the action with the specified <paramref name="data" />.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="formSubmitContext">The form submit context.</param>
        /// <returns><c>true</c> if the action is executed correctly; otherwise <c>false</c>.</returns>
        protected override bool Execute(SendEmailData data, FormSubmitContext formSubmitContext)
            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));

            if (!formSubmitContext.HasErrors)
                // Process formSubmitContext here...
                 var emailBody = "Custom Email Message"; // Set custom email body message here...
                data.Body = data.Body.Replace("#email#", emailBody);
                base.Execute(data, formSubmitContext);

            return true;

Hope this helps!

To know about Sitecore forms, please refer Sitecore documentation for details-

Also If you want to checkout my latest Sitecore videos, you can do so here on Youtube-

Happy learning πŸ™‚

Install Items to custom location using SXA Scaffolding Scripts

Scaffolding in Sitecore lets you add modules/components to tenants and sites. OOTB SXA modules are stored in Feature or Foundation folder:

  • /sitecore/system/Settings/Feature/Experience Accelerator
  • /sitecore/system/Settings/Foundation/Experience Accelerator

In addition to that we can create our own custom SXA components/modules which can be installed just like regular SXA modules.

The SXA components we build could have some site items which we want to install to specific location(s) when this component gets installed like specific data/settings/dictionary/under home etc… This is where SXA scaffolding comes into picture- it enables module-items to install into custom location(s) based on the component requirements so that content authors doesn’t have to install it manually and we give them a seamless module installation experience.

Scaffolding can be configured on tenant or site level, you can see scaffolding options when you create a module, below screen shot for ref.

We have OOTB options to create items to some default location(s) like:

  • Under home item
  • Under Data
  • Some standard items under Presentation and Settings.

For e.g. we can create item of type “AddItem” and specify the location and template, to define where and what type of item we want to create, this helps in installing item(s) in some standard location(s) supported by SXA.

How about if we want to install some item(s) into such location(s) which doesn’t support OOTB by scaffolding action items?

Problem statement : We want to create dictionary items under Site-> Site Dictionary->[Component Dictionary Item] while installing a new module to specific site.

So, how we go there? – we can leverage ExecuteScript action item and write script to create item(s) in any specific location, here are the steps to follow:

  1. Navigate to your site setup item.
  2. Right click on site setup item and create an item say [AddDictionary] based on “ExecuteScript” template.
  3. The script which we are going to create will be referred in the field called “Script” under section “Script
  4. Navigate to /sitecore/system/Modules/PowerShell/Script Library and Create an item say. [TestModule] of type “PowerShell Script Module” template.
  5. Right click on [TestModule] item and create an item say [Functions] based on “PowerShell Script Library” template
  6. Right click on [Functions] and create following scripts:


This script is used to create dictionary item under site->site dictionary domain> for selected site.

Import-Function Get-DictionaryDomain
function Invoke-ModuleScriptBody {
[Parameter(Mandatory = $true, Position = 0 )]
[Parameter(Mandatory = $true, Position = 1 )]
begin {
Write-Verbose "Cmdlet Invoke-ModuleScriptBody – Begin"
process {
Write-Verbose "Cmdlet Invoke-ModuleScriptBody – Process"
$dictionaryDomain = Get-DictionaryDomain $Site
$dictionaryDomainItem= Get-Item -Path $dictionaryDomainPath
# dictionary branch template Id…
$templateId = "{BC8C810C-ACAC-4C40-9A37-036BC6B2B93D}"
New-Item -Parent $dictionaryDomainItem -Name "TestModuleDictionary" -ItemType $templateId
end {
Write-Verbose "Cmdlet Invoke-ModuleScriptBody – End"


This script returns the dictionary domain item based on selected site node and called from Add-SXAModuleDictionary script.

function Get-DictionaryDomain {
[Parameter(Mandatory=$true, ValueFromPipeline = $true, Position=0 )]
begin {
Import-Function Test-ItemIsDictionaryDomain
Write-Verbose "Cmdlet Get-DictionaryDomain – Begin"
process {
Write-Verbose "Cmdlet Get-DictionaryDomain – Process"
Get-ChildItem -Path $Root.Paths.Path -Recurse | ? { (Test-ItemIsDictionaryDomain $_ ) -eq $true } | Select-Object -First 1
end {
Write-Verbose "Cmdlet Get-DictionaryDomain – End"
view raw Get-DictionaryDomain hosted with ❤ by GitHub


This script filters the dictionary domain item based on items from selected site node and called from Get-DictionaryDomain script.

function Test-ItemIsDictionaryDomain {
[Parameter(Mandatory=$true, ValueFromPipeline = $true, Position=0 )]
begin {
Write-Verbose "Cmdlet Test-ItemIsDictionaryDomain – Begin"
process {
Write-Verbose "Cmdlet Test-ItemIsDictionaryDomain – Process"
# dictionary domain template Id…
[Sitecore.Data.ID]$DataSourceConfigurationsTemplateID = "{0A2847E6-9885-450B-B61E-F9E6528480EF}"
end {
Write-Verbose "Cmdlet Test-ItemIsDictionaryDomain – End"

Once you have all the scripts created, navigate back to your site setup scaffolding and click on [AddDictionary] item which you created above in step#2 and set[ Add-SXAModuleDictionary ] script to the Script field.

Next- try to install the module using script->Add site module and select your related module and after the script execution is over you can go back to your Site-> Site dictionary domain-> and you should see [TestModuleDictionary] item created there.

This way you can perform any kind of operation while you are installing specific module to a site, this was just an example to show how you can leverage this feature to provide a seamless module installation experience to your authors.

Hope it helps!

Happy learning πŸ™‚


Sitecore Boxever training

Last week I got a chance to took Boxever eLearning training from Sitecore eLearning platform ,content of training was great and it has covered following details:

  • Boxever CDP, including how it can be leveraged in Segments, Decisioning, and Experiences
  • Identity Resolution
  • Decision Model Notation
  • Personalization across web-based apps and
  • Full-stack and A/B tests that run across a full technology stack

Details about Customer Data Platform (CDP) is great and explained very well like how the CDP layer can act as a great way to connect missing dots between the organization and customer.

Training also includes details about how personalization can setup based on data from Customer data platform and Decision Model Notation and other inputs.

In between we also got few questions(all multiple choice questions) to answer to check what we have learned so far.

It also include details regarding how we can run A/B tests and how to execute it via this platform.

This was all in a nutshell, I would suggest to take this training and see how this works after all it’s officially part of Sitecore ecosystem now, for me details check

Also- in the end there was “Boxever Advanced Certification“, there were 30 multiple choice questions for which we had 1 hr. of time, I am sure you won’t need 1 hr. to complete that.

Happy learning πŸ™‚

Sitecore MVP 2021

Honored to have been awarded Sitecore MVP 2021 under Technology category, 4th time in a row! Thanks Sitecore for this incredible recognition and appreciating the community contributions made last year.

I feel proud to be one of the Sitecore Technology MVP from 170 Sitecore Technology MVPs and 284 Sitecore MVPs altogether this year, this feels great.

I would like to thanks my family, my community friends, my Valtech colleagues and Sitecore for this.

Looking forward to share more with the community.


Setting up Sitecore Lighthouse Demo like a pro

If you are looking to explore SXA (Sitecore Experience Accelerator) and don’t know where to start then Lighthouse demo is the place for you.

Lighthouse Demo is built using Sitecore Experience Accelerator (SXA) on Sitecore Experience Platform (XP) following the Helix principles.

Important to note here is Lighthouse Demo can only be deployed inside Docker Containers (so basic docker knowledge is required).

The idea behind this post is to share my experiences setting up Lighthouse Demo in my local environment issues encountered and resolutions based on the setup guide shared here-

So, let’s get started and check the prerequisites first:


  • Windows 1809 or higher. Version 1909 is preferred.
  • At least 16 Gb of memory. 32 Gb or more is preferred.
  • A valid Sitecore 10 license file located at C:\license\license.xml
  • The latest Docker Desktop.

Docker Readiness:

  • Make sure you are running Windows containers.
  • Ensure the Windows Docker engine experimental features are enabled (to allow the Linux smtp container to run at the same time as the Windows containers)
  • Go to Docker Desktop taskbar icon, right click on it and click on Settings.
  • Go to Docker Engine and add “experiemental” : true, this is how it will look after you add the key.
  • Click on “Apply & Restart” button to restart your Docker Engine.
  • Also- ensure the value of the “dns” key is set to at least [“”].
  • Click on “Apply & Restart” button to restart your Docker Engine.

Ok, at this point we are ready to proceed with the installation, so let’s do it.

  1. Clone the Sitecore.Demo.Platform repository locally
    1. https: git clone
    2. ssh: git clone
  2. Open Powershell as administrator and navigate to the folder where you cloned the repo, in my case it was D:\Projects\Sitecore.Demo.Platform
  3. Create certificates and initialize the environment file
    1. .\init.ps1 -InitEnv -LicenseXmlPath C:\license\license.xml -AdminPassword b
    2. You can change the admin password and the license.xml file path as per your local configuration.

4. Next step is to pull the latest Docker images- docker-compose pull

5. Next step is to start the demo containers, but before that make sure to stop IIS- iisreset /stop, This is required each time you want to use the demo as the Traefik container is using the same port (443) as IIS.

6. Now-start the demo containers- docker-compose up -d

It was going fine for initial few mins- but soon I got the below error “Failed to open

The fix was quite easy and it’s mentioned already here- , just make sure to add the dns key exists with value “” in docker engine json file.

After updating the dns key and value it resolved the error and continued with docker compose up once again.

At step #26 “RUN .\packaging\generate-update-package.ps1” there was one another error, to me everything was fine.

After some time I was able to figure out this and was able to fix it by installing latest version of Docker Desktop (I had version 2.3 so I installed the latest one i.e 2.5) and the error got resolved and the docker compose up completed successfully.

During compose up there was an error related to solr “cannot start service solr” and one of my solr instance was running on 8984 port, when i stopped the service everything was fine

So it’s important to make sure that following ports are not being used by any process- 443, 8079, 8081, 8984, and 14330 as the default Sitecore container configuration uses these specific ports.

You can now check the progress of the initialization by viewing the init container’s logs- docker-compose logs -f init

and after few mins -here you go:

Browse to https://cd.lighthouse.localhost and you should see the Lighthouse landing page with a full-width carousel.

Browse to Browse to https://cm.lighthouse.localhost/ and you see the same carousel

Once you are done you can just stop the container – docker-compose stop

It’s great to start exploring Lighthouse Demo to understand SXA and docker (given the work and effort which Sitecore is putting in docker, it’s high time to start exploring docker ASAP)

I would like to thank Sitecore demo team for their efforts and containerizing Lighthouse demo.

Hope it helps.

Happy Learning πŸ™‚


Sitecore Horizon 10 Installation and Process Failure Error Fix

In this post I would like to share my experience installing Sitecore Horizon 10 in my development machine and issue I faced.

Before anything else let’s checkout the prerequisites for Sitecore Horizon 10


  1. Install Sitecore Experience Platform 10.0
  2. Ensure that your Sitecore Content Management (CM) site is accessible with the https protocol.
  3. Enable support for the WebSocket Protocol in Windows Server Manager.
  4. Ensure Sitecore Identity is installed.
  5. Install Sitecore Installation Framework (SIF) 2.3.0
  6. Install Core 2.1


Once you have the prerequisites in place, next step is to install Horizon, so let’s do that.

  1. Login to
  2. Download Sitecore Horizon 10 from here
  3. Download package for On Premises deployment.

4. Extract the package and open InstallHorizon.ps1

param (
  [string]$horizonInstanceName = "",
  [string]$horizonPhysicalPath = "D:\Deploy\SC9\$horizonInstanceName",
  [string]$horizonAppUrl = "https://$horizonInstanceName",
  [string]$sitecoreCmInstanceName = "",
  [string]$sitecoreCmInstanceUrl = "https://$sitecoreCmInstanceName",
  [string]$sitecoreCmInstansePath = "D:\Deploy\SC9\$sitecoreCmInstanceName",
  [string]$identityServerPoolName = "",
  [string]$identityServerUrl = "https://$identityServerPoolName",
  [string]$identityServerPhysicalPath = "D:\Deploy\SC9\$identityServerPoolName",
  [string]$licensePath = "D:\License\license.xml",
  [bool]$enableContentHub = $false,
  [ValidateSet("XP", "XM")]
  [string]$topology = "XP"

Update the parameter values as per your instance configurations and run the script, it would take somewhere between 5-7 mins and you will be there.

In my case the script ran successfully and there were no errors, so I thought I am good to go and ready to play after seeing Horizon Icon in the launchpad.

When I clicked on Horizon Icon from launchpad it displays the below screen.

The most common root cause which I have seen for the above error is missing license file( i.e. change in the license path) but in my case the issue was not this, the root cause of the error was wrong version of dotnet core, i installed the correct version from here and wooohooooooo here we go….

Welcome to Sitecore Horizon 10

Horizon metadata view.

So I would suggest to check which version of dotnet core has been installed- or if that’s installed at all? in case you see above error.

Apart from this everything else was smooth and the documentation provided with the setup is self explanatory and clear, so you won’t find it confusing.

Hope it helps.

Happy Learning πŸ™‚

Sitecore 10.0 Installation errors and fix

Ok, so we have Sitecore 10 ready to play now which means long list of blog posts on how to install 10 and etc.. I know the hard work is already been done nicely and I don’t want to repeat that all again.

The idea for this post is to share the issue(s) which I encountered while installing Sitecore 10 via SIA.

Issue while creating shard databases-

I got an issue on step #52 where it tries to create shard databases and it breaks.. booooom.. so what’s next?- yes- you are right, I first checked if I am aligned with Sitecore with respect to the installation guide and you know what, I was pretty much aligned, so what’s the issue then?

The issue was related to ScriptDOM dll and I fixed it by removing the reference of ScriptDOM from GAC using gacutilΒ  tool, for more details check this-

In addition to this If you are installing Sitecore along with SXA in a different root location instead of default C:\inetpub\wwwroot – please make sure you have all the parameter values updated to reflect the new path, this is what i got while it was installing SXA:

Apart from this it’s pretty smooth and same as what we did on 9.3.

Hope this helps.

Happy learning πŸ™‚

Fixed installation error with Sitecore.Xdb.Collection.Database.SqlShardingDeploymentTool.exe returned a non-zero exit code

For a POC on Sitecore- I was installing Sitecore 10 using Sitecore Install Assistant (SIA) few days back and in the process I ran into an issue where it breaks at step #52 (creating shards).

Everything was fine as per the Sitecore 10 Installation guide, all the modules and utilities were installed like – Microsoft.SqlServer.TransactSql.ScriptDom, Microsoft.SqlServer.Types.dll and Microsoft.SqlServer.Dac.dll.

I used the same setup to install Sitecore 9 (9.3 to be precise) before and it worked like a charm.

Also, I checked and found that path to “Data-Tier application framework”, “SQL ScriptDOM” and “CLRTypes” were also added to registry as mentioned in some of the articles.

Observed the following error for ref.

[ XConnectXP0_SetServicesCertStorePe... : FilePermissions ---------------------]
[XConnectXP0_SetServicesCertStorePermissions]:[Allow] NT AUTHORITY\LocalService
[XConnectXP0_SetServicesCertStorePermissions]:[Path] C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\7c7bac47142b92c79c036c95fd8760ac_d0ab05c7-b351-4434-adff-53512d7e05d0
[XConnectXP0_SetServicesCertStorePermissions]:[Rights] Read
[XConnectXP0_SetServicesCertStorePermissions]:[Inherit] None
[XConnectXP0_SetServicesCertStorePermissions]:[Propagate] None

[------------- XConnectXP0_CleanShards : Command -----------------------------]
[ShardingTool - Clean]:[Path] D:\Deploy\SC9\\App_Data\collectiondeployment\Sitecore.Xdb.Collection.Database.SqlShardingDeploymentTool.exe

[------------ XConnectXP0_CreateShards : Command -----------------------------]
[ShardingTool - Create]:[Path] D:\Deploy\SC9\\App_Data\collectiondeployment\Sitecore.Xdb.Collection.Database.SqlShardingDeploymentTool.exe
Command D:\Deploy\SC9\\App_Data\collectiondeployment\Sitecore.Xdb.Collection.Database.SqlShardingDeploymentTool.exe returned a non-zero exit code - (2)
[TIME] 00:04:26
Command D:\Deploy\SC9\\App_Data\collectiondeployment\Sitecore.Xdb.Collection.Database.SqlShardingDeploymentTool.exe returned a non-zero exit code - (2)

I had two versions of SQL- 2017 and 2019, but 2019 was installed later, i tried to run the script before with 2017 also but it didn’t worked.

Solution- As next step- I removed the reference of “Microsoft.SqlServer.TransactSql.ScriptDom” from GAC using gacutil tool, ran it again and it worked fine, i think some how it was not able to pick which version of ScriptDom to take and part of this process it removed version and of ScriptDom from GAC .

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\gacutil" -u Microsoft.SqlServer.TransactSql.ScriptDom

This was annoying but finally was able to get through this, thought of sharing this here so it helps others in future.

Hope it helps.

Happy learning πŸ™‚

Installing Sitecore Horizon 9.3 in a custom location

As some you might be aware of Horizon is the next-generation editor in Sitecore Experience Platform. Horizon includes the following features:

  • The page editor, which you use to create and edit web pages. As you edit a page, you can see how it will appear on different devices.
  • Simulator mode, which you use to preview web pages as they will appear on different dates and on different devices.
  • Insights view, which you use to see analytics for your web pages.

Installation of Horizon is quite simple and it’s a matter of 4-5 mins to get Horizon up and running on top of your running Sitecore 9.3/10 instance.

Sitecore Horizon gets installed by default to “c:\inetpub\wwwroot\…” location, but how about if you want to install Horizon to custom location and not to the default one?, consider a case where you have you Sitecore installed into a custom location and you want to follow same for Horizon as well.

I was checking all Horizon configurations to see if there is a way around to install it to a custom location the way I did for Sitecore 9.3 and while I was checking this I found an article by Gullentops here- where he has explained the changes that are required to make it happen.

So, basically the changes are required on three files:

Configs/sitecore-ah.json– Here we need to update AuthoringHost.Site.PhysicalPath variable to the path as required.

"AuthoringHost.Site.PhysicalPath": "[joinpath(environment('SystemDrive'), 'inetpub', 'wwwroot', variable('AuthoringHostSiteName'))]" 

Configs/sitecore-cm.json– There are two changes required here:

  1. Change the parameter Site.PhysicalPath (line #15) to SitePhysicalPath
  2. Change the parameter name in the definition of Site.PhysicalPath variable (line #46) – the variable can keep the “.” in the name
"Site.PhysicalPath": {
			"Type": "string",
			"DefaultValue": ""
"Site.PhysicalPath": "[if(equal(parameter('Site.PhysicalPath'), ''), variable('Site.PhysicalPath.Default'), parameter('Site.PhysicalPath'))]",

and the last change on parameters.ps1 file:

  1. Add SitePhysicalPath = “site-cm-path” to the $sitecoreCM parameters
# Configure Sitecore
$sitecoreCM = @{
    Path                      = Join-Path $configsRoot sitecore-cm.json
    SiteName                  = $ContentManagementInstanceName
    AuthoringHostSiteName     = $authoringHostName
    WebProtocol               = $ContentManagementWebProtocol
    HorizonFeatureIntegrationPackageFolder = Join-Path $PSScriptRoot "resources"
    HorizonFeatureIntegrationPackageName = 'Horizon.FeatureIntegration'
	SitePhysicalPath          = "D:\Deploy\"

2. In $sitecoreIS parameters section, set the AuthoringHostPhysicalPath to the path you want to set for your authoring site- in my case it was set to


# Configure Sitecore Identity Server
$sitecoreIS = @{
    Path                       = Join-Path $configsRoot sitecore-is.json
    AuthoringHostSiteName      = $authoringHostName
    AuthoringHostPhysicalPath  = "D:\Deploy\"
    # Please fill in physical path to Sitecore IdentityServer. Example: c:\inetpub\wwwroot\horizon-IdentityServer
    SitecoreIdentityServerPhysicalPath = $SitecoreIdentityServerPhysicalPath
    SitecoreIdentityServerPoolName = $SitecoreIdentityServerPoolName
    SitecoreIdentityServerSiteName = $SitecoreIdentityServerSiteName

Fill in the other details as required in the file and you should be good to go.

For Sitecore Horizon version 10- we don’t need to do this hack- we just need to update $horizonPhysicalPath parameter to the location we want to install horizon and you are good, no more parameter updates.

Hope this helps.

Happy learning πŸ™‚

Quick References:

Config Transforms and Roles in Sitecore

There are scenarios when we want to change value of some setting(s) based on environment, like DEV/QA/Staging/CM/CD1/CD2 and etc..
For example- we have an API URL which varies based on environment, so how you can have different values for different environments, we can make use of transformations config using Slow Cheetah and set different values across environments.

You can read more about Slow Cheetah transformations here-

It’s super useful when you want to :

  1. Have different AppSettings for debug and release when building your app.
  2. Use different connection strings based on your build configuration when building your app.
  3. Transform any XML file with a clean and simple syntax.

Setup and Installation:

You just need to install and setup “SlowCheetah” nuget package and Visual studio SlowCheetah extension and you are good to go.

Once Slow Cheetah is installed- In your ‘App_Config’ folder, right click on the file(this includes ConnectionString, app settings or any other config you have) you want to perform a transform on and select ‘Add Transform‘. This will add variations for each configuration build we have setup in our project like (UAT CD1,UAT CD2, PROD CD1, PROD CD2, STAGE CD1,STAGE CD2 etc):

For web projects the files are transformed when you publish or package your application.

Some of the commands which you can use to transform the configs are as follows:

To Insert:

If you want to add/Insert some setting into specific environment(s) like CM/CD, you can use the below syntax on specific configuration build transformation config file.

<add name="MySetting" value="Setting Value" xdt:Transform="Insert"/>

If you want to remove specific setting from environment(s) like CM/CD, you can use the below syntax on specific configuration build transformation config file.

To Remove:

<setting name="MySetting" value="Setting Value" xdt:Transform="Remove" xdt:Locator="Match(name)"/>

If you want to replace some value for specific setting from environment(s) like CM/CD, you can use the below syntax on specific configuration build transformation config file.

To Replace:

<setting name="MySetting" value="New Value" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>

How to transform in Sitecore 9?

From Sitecore 9 we have an option to configure different values for different servers and environments via Rules Based Configuration. so no more config transforms to change the values, we simply need to update the config roles by one of the role available:

Following roles are available:

  • ContentDelivery
  • ContentManagement
  • Processing
  • Reporting
  • Standalone

Below are the supported roles for Sitecore 9.3 which is present in web.config file and we need to define/set role:define attribute to the correct server role.

         Specify the roles that you want this server to perform. A server can perform one or more roles. Enter the roles in a comma separated list. The supported roles are:

         ContentDelivery, Indexing
         ContentManagement, Indexing
    Default value: Standalone
    <add key="role:define" value="Standalone" />

For example- if we want to deploy specific setting only in ContentManagement or Standalone role we can specify it like this:

<setting name="CookieExpiryValue" value="1" role:require="Standalone or ContentManagement"/>

So things are made easy in terms of configs changes across environment and also regarding server configurations.

Note: If you are upgrading from Sitecore 8 to 9 you have to make a note of this and if you have any transformation configs present- it would be better to use Sitecore roles instead of transformation configs.

Sitecore Custom rules:

In addition to default server roles mentioned above, if you want to control some values across environments like Dev, INT, Staging CM or UAT CM we can create custom roles and use these custom roles along with server roles to define the changes.

How to define a custom rule:

In the web.config file, in the <appSettings> section, add a line specifying the rule.


<add key="localenv:define" value="Dev">


In the above section we have created a custom rule called “Dev“- so if we want to execute/deploy config which is based on Standalone Server role and Dev custom rule we need to define below:

<setting name="MySetting" value="TestValue" localenv:require="Dev">

We can also specify multiple rules to configure like below:


<add key="localenv:define" value="Dev, INT, Staging CM, UAT CM, PROD CM">


Recently we upgraded from 8.2 to 9.3 for and we changed the transformation part to Sitecore roles to control and deploy configs across environment and the change was easy and neat.

In addition to this we also have an option to test how the configurations looks like on different server role.

You can access the page from content management server and get to see the configs for different server role- http://yourhost/sitecore/admin/ShowConfigLayers.aspx

Hope this helps.

Happy learning πŸ™‚