Sitecore-how to create custom personalization rule

Personalization is the method for displaying targeted and relevant content to  website visitors based on different characteristics  like location, age, visits, etc.. There are several rules available out of the box in Sitecore which can be leveraged to personalize web pages.

Personalization-2

It is also possible that we have to build and create custom personalization rules to support certain business requirements, Sitecore architecture is flexible enough to support this scenario and can be extended to implement custom rules based on the requirement.

As part of this post, i would like to show how we can extend and build custom personalization rules, we will take an example of creating a custom rule where based on querystring parameter value how we can display different content to our site visitors.

Let’s take an example where we would like to show website visitor component-1 when user search for keyword=”content” and show component-2 when user search for keyword “management”.

Here are the steps to follow:

Step 1- First step is to create a new tag for our Custom rule under “/sitecore/system/Settings/Rules/Definitions/Tags” based on template- “/sitecore/templates/System/Rules/Taxonomy/Tag”

Sitecore-Tag

Step 2- Next- create custom Element and personalization condition under “/sitecore/system/Settings/Rules/Definitions/Elements”

Personalized-Rules

As part of personalization condition there are two fields to populate:

  • Text
    • It shows text that would be presented to content editors when using this condition with Rules Engine, this is what we have used in this example-
    • Where the querystring parameter search has a value that [operatorid,StringOperator,,compares to] [querystringvalue,,,Value]

    • Everything under square brackets []  would be replaced by Rules Enging as selectors.
  • Type
    • Type specifies fully qualified class and assembly names where we want to write/perform the business rule for the custom personalization condition.

Step 3- Next step is to assign custom tag which we created in step#1 to default element tag definition.

Element-tag

Step 4- Next- we would need to add this tag to conditional rendering such that this new rule is available in the rule editor for content editors to personalize the components, please make sure to name your tags and custom elements self explanatory as much as possible for better content editors experience.

conditional-rendering

Step 5- Once all the above changes are made content/business editors can configure this rule to personalize the components from experience editor or content editor from presentation->Personalize section.

rule-editor

In the below code snippet we can see that we have created a class SCCustomRule which inherits StringOperatorCondition class and override Execute(T ruleContext) method -as we are trying to compare the querystring value of what has been configured in the rule editor and what has been actually entered by end user.

If the parameter values matches the rule is satisfied and the personalized component will be displayed else it would display the default component.

custom-personalization-snippet

Similarly we can create other custom rules to show more relevant and targeted content to our end users based on how they have interacted and what details they have stored in the system (internal/external)

Hope this helps.

Happy learning 🙂

Return null or String.Empty for Computed fields in Sitecore

It is quite obvious that we have to create computed fields in Sitecore, to process some of the information well before it get indexed, and not processing it while requesting for the data.

ankit-sitecore-download

There are chances when you don’t find any value to be added to you computed field, in those cases we can return either null or String.Empty().

Returning null basically tells that there is nothing to be indexed, and it won’t take any space in your index, but when we return string.Empty() , it actually creates an entry in index with no value.

Returning String.Empty() is helpful when you want to validate something based on empty string, but most of the case it is not worth.

Also, consider a case when you are dealing with several thousands Sitecore items, and if you are going to return String.Empty() for few thousands also, it will just get indexed that takes up space in you index.

We should carefully think about this, if there is a need to return String.Empty() we should do the same, but if not we should always try to return null.

Hope this helps someone.

Happy learning 🙂

Introduction to Sitecore Patching

There are several instances when you make updates to your Sitecore.config file, changes can include:

  • Adding new pipelines and processors for any custom feature implementation.
  • Updating/overriding the default values for some of the setting values like cache sizes and etc.
  • Adding new Sitedefination for your Sitecore instances.

So, to make any of the updates mentioned above, we have to perform following task(s):

  • Code changes (class file updates) and/or
  • Configuration file(s) changes (this is to make sure we register the changes in Sitecore)

Once you are done with you class and config changes, we need to register the changes in Sitecore, this is required so that Sitecore can identify the changes you made, and the functionality works as expected.

There are two approaches for registering the custom updates in Sitecore:

  1. By adding/updating the config changes directly in Sitecore.config file (not recommended)  or
  2. Creating a patch file (with extension .config)  which includes all the changes required, and placing file under App_Config/Include folder, we can create separate sub folders as well.

 

ankit-sitecore-download

Both the approaches works fine as expected, but there is an issue with approach 1.

How would you handle the updates in Sitecore.config file when you are planning for an upgrade later?, provided that you made several changes to Sitecore.config file, it may results issues after the upgrade.(think about it carefully before making changes directly to default Sitecore.config file)

How about if we think about creating a patch file, and putting all our changes there?, and this works well even if you are going for an upgrade at later stage, as you are not adding/updating anything on default Sitecore.config file directly, all the custom changes are coming as part of your patch file(s), This also helps in easy maintenance and troubleshooting.

Patch files are merged with Sitecore.config in alphabetical order. This means configuration in a patch file named a.config will appear before configuration in a patch file named b.config.

If the same configuration is found in multiple patch files, the configuration from the last patch file processed is the configuration that is used.

We can create as many patch files as we want, it all depends on the feature/requirement(s) and the way you want to organize your configuration files in your solution.

For example – you can create separate patch file for any Import functionality we have in the system, and this includes all the settings that needs to be added for specific one, also, there can exists separate patch file which includes custom indexes if exists any?

Note: Patching only works on the Sitecore configuration section, no other file or section can be patched with this.

Place in solution where patch files are placed, i.e under “App_Config/Include” folder

/App_Config/Include/zCustom.config
/App_Config/Include/events/zCustomEvents.config
/App_Config/Include/etl/zCustomEtl.config

Sitecore patching can be used for following operation(s):

  1. Adding a new setting
  2. Deleting a setting
  3. Adding or updating an attribute.
  4. Inserting an element before a specific element.
  5. Inserting an element after a specific element.

Simple example of Sitecore Patching:

This will set the default database for your website to master, this helps in testing the application without publising changes to web db
(Make sure to revert it back once you are done- and never make this change in QA/Production)

Sitecore-patching

How to see the result after Patching?

Now, how we can see the file which includes all the patches which we have applied, there is no physical .config file which can be used, In order to see the final result, please use this URL

http://%5Byour-localhost-name%5D/sitecore/admin/ShowConfig.aspx

Sitecore patching is an important part of day to day development, and we should leverage this as much as possible, to make sure we can make the system more stable and maintainable.

You can learn more about Sitecore Patching here:

Thanks and let me know if you have any feedback/comments on the same.

Happy learning 🙂

Setting up Sitecore Active Directory Module

Active Directory module provides the integration of Active Directory domain with the Sitecore solution.We can integrate the domain users and groups available into Sitecore CMS as Sitecore users and Sitecore roles.

AD1.3

As part of this blog we will be using Active Directory Module 1.3 which runs on Sitecore 8.2, the complete list of modules can be checked here- https://dev.sitecore.net/Downloads/Active_Directory.aspx

Download AD Module 1.3 from here- https://dev.sitecore.net/Downloads/Active_Directory/1_3/Active_Directory_1_3.aspx

Once Module Installation is completed, here are the next steps i followed:

Modifying Config files:

Connectionstring.config

In connectionstring.config file, add a new connectionstring which has AD details , in the following screenshot it’s just a test OU name, but you will be replacing this with real OU, you can also apply filters for OU, so that you are exposing only those groups which are expected and required to be a part of Sitecore, like Admin,IT, Sales and etc.

AD-connection-string

Domains.xml.config

Open Domains.config.xml and add a new domain to it, file can be found here- App_Config->Security->Domains.xml.config

AD-domain-config

Web.config– MembershipProvider

Add new membership provider.

<add name=”ad” type=”LightLDAP.SitecoreADMembershipProvider” connectionStringName=”LDAPConnString”
applicationName=”sitecore” minRequiredPasswordLength=”1″ minRequiredNonalphanumericCharacters=”0″
requiresQuestionAndAnswer=”false” requiresUniqueEmail=”false” connectionUsername=”username
connectionPassword=”password” connectionProtection=”Secure” attributeMapUsername=”sAMAccountName”
enableSearchMethods=”true” />

AD-membership

Web.config– RoleProvider

Add new role provider.

<add name=”ad” type=”LightLDAP.SitecoreADRoleProvider” connectionStringName=”LDAPConnString” applicationName=”sitecore”   <add name=”ad” type=”LightLDAP.SitecoreADRoleProvider” connectionStringName=”LDAPConnString” applicationName=”sitecore”      username=”username” password=”password” attributeMapUsername=”sAMAccountName” cacheSize=”50MB” />

AD-role

Web.config– ProfileProvider– (Optional)

Note: We need to have an AD user to perform LDAP queries, else you won’t be able to connect to your AD Instance, the same username and password will be set to membership and role provider.

Activating Switching providers:

In web.config  file,in <system.web> section, browse for <membership> element and find the provider called sitecore and set its realProviderName attribute to switcher.

In web.config file, in <system.web> section, browse for <roleManager> element find the provider inside called sitecore and set its realProviderName attribute to switcher.

Adding the Domain-Provider Mappings:

This will be done in sitecore.config

AD-domain-provider

Now, we are done with all basic configuration(s) which are required to be added and configure in order to start using Active Directory Module, go ahead and test it.

Login to Sitecore using admin, and you should be able to see users and roles from AD instance, from this point you can give add AD users to CMS roles, once this is done, please try to login using AD user.

When i was working on this, i tried to login using AD user, and got this error.

AD-user-login-error

Sitecore has provided hot fix for this, and upon applying the fix, i was able to login to Sitecore using AD credentials.

https://kb.sitecore.net/articles/520134

After applying the patch, try to load Sitecore again and you should be all set now.

Hope this helps somebody.

I am working on integrating this module with Sitecore Paas (Azure), and will share the findings with the community soon.

Happy learning 🙂

Content managed favicon in Multisite Sitecore solution

There are scenarios when we want to configure content managed favicons for multiple sites in the same instance of Sitecore.

I have implemented this for one of our client, so thought of sharing the same with the community.

In my case, we have separate Site settings node created, which has all site related information, from the below screen shot you can see we created a new field called “Fav Icon” which is of file type.

FavIconField

Once we have the field available, content authors can content managed the fav icon based on the site requirement, please see the screen shot for ref:

Favicon

In the below code snippet, we are trying to fetch the sitenode based on start node(home node), and once we have sitenode, we are fetching site settings node from where we can get “Fav Icon” Url value.

 public static Item ContextWebsiteRoot
 {
   get
   {
     Item contextItem = null;
     Item webSiteContext = null;
     if (Sitecore.Context.Site != null && Sitecore.Context.Database != null)
     {
        Item homeNode = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
        webSiteContext = contextItem.Parent;
        // Use webSiteContext to get "Fav Icon" url...
        // We don't have to use .Parent, if "Fav Icon" field is created directly 
        // under home node.
     }
     return webSiteContext;
   }
 }

In my case we don’t have the Fav Icon in the site home node, so we need to add some rule to get the correct item, and then reading “Fav Icon” field, but just in case, if you are trying to add “Fav Icon” field directly in home node, you don’t need to fetch any parent Item.

Here is the simplified version of it, when “Fav Icon” is added to home node.

 Item contextItem = null;
 Item webSiteContext = null;
 if (Sitecore.Context.Site != null && Sitecore.Context.Database != null)
   {
      Item homeNode = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
      var siteFavIcon= contextItem["Fav Icon"];
   }

 

I hope this helps someone who is trying to implement something similar.

Happy learning 🙂