Sitecore 9 – Whats New?

Sitecore revealed the latest version of their customer experience platform at the Los Vegas Symposium 2017, Sitecore 9. The following is brief overview of whats available.

The name!

Sitecore have changed the name from Customer Experience Platform to Experience Cloud.

Sitecore xConnect

xConnect is a new API which allows developers to integrate data collected by Sitecore with other third party sources. Reading data from the xDB has now been standardised via the xConnect service layer.

Sitecore Cortex

Cortex is a new machine learning engine purpose build for Sitecore. It helps discover new audiences and is able run multi-varient tests. Future development of Cortex will bring automated personalisation and is expect to make an appearance towards the latter part of 2018.


First quarter 2018 will bring Sitecore Commerce 9. This will bring a more mature and fully integrate e-commerce solution. Build in .Net Core the new solution will replace Commerce Server. The old store front will be replaced by SXA compomants.


Microsoft and Sitecore have improved the offerings available from the Azure Marketplace. Its now possible to pick your Sitecore version (all 8.2’s and 9) along with topology and size. While is a simple and quick way to spin up a Sitecore install your are limited to pre-made packages. For customer installs, its still advisable to use the Azure Resource Manager (ARM) templates instead.

Sitecore Forms

Web Forms For Marketers (WFFM) has finally been replaced. Sitecore Forms has new look with full drag and drop support. It also includes multipage forms and conditional logic.

Federated Authentication

Sitecore finally offers federated authentication via OWIN. This provides integration with SAML, Facebook, OAuth, WS-Federation and ADD.


Sitecore is moving away from its proprietary UI framework (SPEAK) to a commodity based strategy, Angular First.

Sitecore Installation Framework (SIF)

Installing Sitecore 9 is different from previous versions. The single executable installation method is now gone. Instead all individual services have been split into their own components. To try and simplify the installation process Sitecore created an installation framework called SIF. It combines Powershell and JSON configuration files to build Sitecore environments. By doing this Sitecore have simplified DevOps and automated deployments.

Sitecore JSS

Sitecore’s JavaScript Services is an API layer on top of Sitecore and lets you hook multiple JavaScript frameworks to Sitecore like React and Vue. Using an OData REST service and API key management, security and data abstraction are also ensured. Together with xConnect, there’s no shortage in what third-party systems or IoT devices you can connect to anymore. By the way, mind that JSS is still in Tech Preview for the Initial Release of 9.0!

Dynamic Placeholders

Until dynamic placeholders have only been available using a Sitecore module or custom code. Sitecore 9 now has built in support.

XDB SQL Support

Sitecore 9 can now write analytics data directly to a SQL Database without going via MongoDB first. In fact the initial release of Sitecore 9 has dropped MongoDB completely, however support will be included in future releases.

Sitecore Zenith and Horizon

While its not included yet, Horizon will change the way content editors interact with Sitecore. This will replace both the Content Editor and Experience Editor with a single solution, providing full drag and drop, device emulation, heat maps and machine learning.

Retrieving site information in Sitecore

Sitecore provides functions to get the root path and start item for the current context. So when working with multisite solutions you should always get a path relative to the Sitecore.Context.Site settings:

Response.Write("Current site: " + Sitecore.Context.Site.Name + "<br/>");
Response.Write("Database: " + Sitecore.Context.Site.Database.Name + "<br/>");
Response.Write("Content start path: " + Sitecore.Context.Site.ContentStartPath + "<br/>");
Response.Write("Home node: " + Sitecore.Context.Site.StartPath + "<br/>");
Response.Write("Language: " + Sitecore.Context.Language.GetDisplayName() + "<br/>");

The code above would give me the following output for the site at

Current site: website_1
Database: web
Content start path: /sitecore/content/website1
Home node: /sitecore/content/website1/home
Language: English : English

Finding a Sitecore item by ID using a Solr query

By default the _group field contains the Sitecore ID for a specific item. To search for an item with an ID of {799539AB-3495-4D40-9B2F-A394A87960D6} use the following Solr query:


Please note the ID is not stored in the group field as a standard GUID. For the search to work hyphens need removing and converting to lower case.

However this will only work for an item with a single version and language. As Sitecore uses the same item for each piece of content, regardless of the number of versions or languages, the above query may return multiple results.

In this case we need to use the _uniqueid field to return the exact item representing a specific version and language. In this example we change the Solr query to:


Unpublish a Sitecore item

Any regular Sitecore users knows there are many ways to publish an item. However it’s not always obvious how to “unpublish” an item. Its actually quite straight forward.

1. Navigate to the item you want to unpublish using the Content Editor. From the Publish ribbon select the Change button:

In change dialog, make the item unpublishable by deselecting the Publishable checkbox:

The content editor will display are warning informing you what’s about to happen.

The final step to actually publish the item and it will disappear from the front-end but remain in the master database. This may sound strange, but as the item is already published we need to publish again to remove it from the web database.

Sitecore Habitat Installation Issues

I’ve recently attempted to setup a Sitecore Habitat solution by following instructions from the GitHub site.

This was not as straight forward as I’d hoped. The following are some issues I had to resolve along the way.

Web Forms For Marketers

Ensure this is installed correctly and working. Although I had installed the module and it appear to be successful, when I checked System/Modules/Web Forms for Marketers items were missing. The problem didn’t become apparent until Unicorn tried to sync items relating to WFFM.

I also discovered although it’s not mentioned in the Habitat documentation MongoDB is required for WFFM to work correctly with Habitat.


After installing NodeJS I ran npm install from the root of the Habitat repository as instructed. However this kept failing while trying to install node-sass with a 404 error. Running npm install node-sass to manually install the package before running npm install resolved the issue for me.

Editing repository files

Make sure any files you’ve been editing are not open by another application

Unicorn Sync

Although the sync process should work fine through Visual Studio Task Runner. I found it more successful to run it through a command prompt using gulp.\


Even after a success npm install I received a gulp command not found error when running gulp from a command prompt. Running npm install –global gulp-cli in the repository root resolved the problem.


Sitecore items not visible on website

Sometimes you may find an item appears in both the master and web database’s. But when you navigate to that item on the live website site either a 404 returned, or in the case of a component it’s not visible.

This could be because the item has publishing restrictions in place. There’s a few places to check:

  1. Log into Sitecore.
  2. Open the Content Editor.
  3. Select the View tab and ensure Standard Values is checked.
  4. Navigate to the offending item using the content tree and select it.
  5. Using the right panel scroll down to the Publishing section.
  6. Check the dates are either empty or valid for displaying the item as of today.
  7. At the bottom of the Publishing section there is a Never Publish checkbox, make sure this is unchecked.

If workflow is in place it might be worth checking the Workflow selection for this item. The state field will highlight where in the workflow this item is. However if the item is’t approved it shouldn’t show in the web database.

If the above doesn’t help its worth republishing the item or its parent..

Sitecore generating Overlapping onDeckSearchers=x warnings in Solr logs

I’ve recently had an issue where every 10 minuets or so a entry would appear in the Solr logs. This was only an issue for the analytics core. After reading various articles and try different Solr configurations I failed to resolve the problem.

However after a chat with Sitecore Support the issue was resolved by a quick change to our Sitecore environment. Our production environment consists of four separate Sitecore instances, two delivery, one authoring and one processing server. By default Sitecore uses a Timed Index Refresh Strategy to update Solr’s analytics core. By having four environments pointing to the same Solr instance, the analytics core was being updated four times simultaneously.

When a processing server is being used only that should update the analytics core. In an environment without a processing server it would the possibility of authoring server.

To resolve the issue the processing server was left with the default Timed Index Refresh Strategy. Automatic updating of the analytics was disabled on the remaining three environments by changing the strategy to manual.

The strategies are set in the Sitecore.ContentSearch.Solr.Index.Analytics.config file. The default is:

<strategies hint="list:AddStrategy">
   <timed type="Sitecore.ContentSearch.Maintenance.Strategies.TimedIndexRefreshStrategy, Sitecore.ContentSearch">
      <param desc="interval">00:01:00</param>

To use a manual strategy remove the above from the config file and add:

<strategies hint="list:AddStrategy">
   <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/manual" />

Rather than updating the config file a better solution would be creating a patch file. This way if the config file is replaced during an upgrade the config change will still be applied.

OctoPack NuGet versioning order

NuGet packages have version numbers. When you use OctoPack, the NuGet package version number will come from (in order of priority):

  1. The command line, if you pass /p:OctoPackPackageVersion= as an MSBuild parameter when building your project.
  2. If the [assembly: FileVersion] is the same as the assembly: AssemblyInformationalVersion, then we’ll use the [assembly: AssemblyVersion] attribute in your AssemblyInfo.cs file
  3. Otherwise we take the [assembly: AssemblyInformationalVersion].

Querying the Sitecore Reporting Database (xDB) Directly

While Sitecore provides comprehensive analytics from the main dashboard, there may be a requirement to interrogate the analytics data directly in your code. To do this we need to make use of Sitecore’s ReportDataProviderBase and ReportDataQuery classes. These provide access to the reporting database using the parameters set in the Sitecore.Analytics.Reporting.config.

Sitecore stores all it’s queries in items based in the ReportQuery template. As of Sitecore 8.1 these can be found at the following location Master/Web > sitecore > system > Settings > Report Queries.

First create a new ReportQuery item by duplicating an existing one. Open your new item and update the Query field with your own SQL query. Once complete save and publish taking note of the item ID.

Next create a method to run the query, below is a basic example:

        public void GetReportingData()
            if (!String.IsNullOrEmpty(searchTerm))
                using (var context = Index.CreateSearchContext())
                    // By using the ReportDataProviderBase and ReportDataQuery Sitecore is instructed to use the Reporting (Analytics database)
                    // defined in the connectionStrings.config

                    // Create ReportDataProviderBase factory using connection info from Sitecore.Analytics.Reporting.config
                    var provider = (ReportDataProviderBase)Factory.CreateObject("reporting/dataProvider", false);

                    // Load SQL from Sitecore ReportQuery item
                    Item dataSourceItem = Context.Database.Items[ID.Parse("{id of ReportQuery item created above}")];
                    var dataSQLQuery = dataSourceItem.Fields["Query"].Value;
                    var query = new ReportDataQuery(dataSQLQuery);

                    // Run query using the FiltersFactory defined in the reporting node from the dataProvider node in the Sitecore.Analytics.Reporting.config
                    // in this case /sitecore/system/Settings/Analytics/Vendor Specific Filters/MSSQL
                    var response = provider.GetData("reporting", query, CachingPolicy.WithCacheDisabled);

                    // Populate list
            return list;