Sitecore CMS & DMS Tips & Tricks

July 29, 2015

Installing Sitecore Commerce Server 8 and the Storefront Sample Site from Scratch

Filed under: Commerce Server,Sitecore — René @ 3:32 AM
Tags: , ,

Since Sitecore bought Commerce Server, they have been working hard at integrating the two closer together. Although this has been going on for some time, the process of installing Commerce Server itself is still not very easy. If you then add on top wanting to get the Storefront sample site working as well, including having it compile in Visual Studio, you’re in for hours of frustration. The many different products required to get everything setup does not make this process easier.

This guide aims at giving you a one-stop guide on how to accomplish this from the beginning to allow you to commence development with Sitecore Commerce Server 8. There’s lots of terminology being thrown around, and no single document seems to describe the process from the beginning, so I’ve attempted to do so, freely borrowing for Sitecore’s documentation where necessary.

This guide will assume you have a fresh install of IIS (with Default Web Site intact, otherwise create it), SQL Server 2012, Visual Studio 2013, and nothing else. It has been tested on a Windows 8.1 machine.

1)
Install Sitecore and MongoDB by following my guide to Installing Sitecore 8.0 and MongoDB in 10 minutes using Sitecore Instance Manager and PowerShell.

This guide has been tested with Sitecore 8.0 revision 150621, so I encourage you to use this version.

For the rest of this guide I will assume you have Sitecore running on http://sc80rev150621 as suggested by the Sitecore Instance Manager and that the physical installation path for this website is C:\Sitecore\sc80rev150621. If you’ve used different values, you need to change where appropriate throughout this guide.

2)
Go to Control Panel > Programs and Features > Turn Windows Features on or off, and ensure you install the following components before you proceed any further.

  • Windows Identity Foundation 3.5
  • IIS Metabase and IIS 6 configuration compability. It’s located under Internet Information Services > Web Management Tools > IIS 6 Management Compatibility. This is required by Commerce Server.
  • ASP. It’s located under Internet Information Services > World Wide Web Services > Application Development Features. This is used for some of the old reports in Commerce Server.
  • Windows AuthenticationIt’s located under Internet Information Services > World Wide Web Services > Security. This is required for the Commerce Server Business Tools to work.

Furthermore, ensure you have installed .NET Framework 4.5.2 Developer Pack.

Also ensure you have Windows Authentication enabled for SQL Server.

3)
Download and install the latest version of the Commerce Server stand-alone software. This is a ~100mb download. Click on this link, login with your Sitecore credentials and click on the Commerce Server link in the left column.

Make sure you complete the Commerce Server Configuration Wizard that appears automatically.  The first screen of the guide can be seen below. Ensure you click the button Test to confirm that it can connect to SQL Server. Otherwise leave the remaining settings as they are.

wizard1

On the next screen (below), enter your Windows password in the Password field.

wizard2

On the remaining screens, you can simply press Next. You have completed the installation when the MSCS_admin database appears in the SQL Server Management Studio Object Explorer.

4)
Install Sitecore Commerce Connect. According to the documentation, “this is an e-commerce framework designed to integrate Sitecore with different external commerce systems and at the same time integrate customer engagement functionality provided in the Sitecore Experience Platform”. I.e. regardless of which eCommerce platform you’d use, you need to install this.

Download it here, go to http://sc80rev150621/sitecore, login, go to the Sitecore Control Panel, then select Install a Package. It mentions a post-installation step, which you can skip for the purpose of this guide.

5)
Download Sitecore Commerce Server Connect by following this link and select it from the left column. Notice that this is separate to the Sitecore Commerce Connect installed in the previous step. This provides functionality only usable with Commerce Server. To install it, go to http://sc80rev150621/sitecore/admin/updateinstallationwizard.aspx and follow the guide.

6)
Download the MVC Site Deployment Scripts from this page (see the left column a bit down on the page). This is a zip filled called Deploy.zip. Unpack it to C:\Deploy (I’ll be using this path throughout this guide). These deployment scripts are used to unpack a site in Commerce Server, so the appropriate site specific databases and web services are installed.

7)
Download the full zip package of the Sitecore Storefront site from Github. This contains all the source files for the Storefront site, so you later can open it in Visual Studio and explore the code.  Expand it into C:\Deploy\Reference-Storefront-master and delete the AX folder and the Commerce.Dynamics.Storefront.sln file as we won’t be using any functionality related to integrating with Dynamics AX.

8)
Copy the six folders from C:\Deploy\Reference-Storefront-master\Storefront\CS\Database into the folder C:\Deploy\Database and overwrite any existing files. This means that when you invoke the deployment scripts, they will use the Storefront prepared Commerce Server databases.

9)
Open C:\Deploy\Deployment\Environment.xml and set the following parameters with the values shown. Notice that all the parameters appear multiple times in the file, and you should replace them whenever they are defined as variables.

Variable Name Existing Value New Value
instanceName CSSitecore sc80rev150621
INETPUB_DIRECTORY $( Join-Path -Path $Env:SYSTEMDRIVE -ChildPath “inetpub” ) C:\Sitecore
SitecorePort 7655 80
scHostHeaderName sc.local sc80rev150621

Also ensure that you have installed MongoDB in C:\MongoDB. If not, you need to change the MongoDB path as well everywhere it appears.

10)
Now we’re ready to execute the Commerce Server scripts that installs the Storefront Commerce Server site.

  • Open a Powershell window
  • Enter Set-ExecutionPolicy Unrestricted and select Y.
  • Browse in the Powershell window to the location C:\Deploy\Deployment.
  • Type ./Deploy-UnPup.ps1 and hit Enter. Type r, then hit Enter, as many times as is required to accept the security warnings.
  • Type ./Deploy-Base-SC-Existing.ps1 and hit Enter. Type r, then hit Enter, as many times as is required to accept the security warnings.

To confirm this has been executed successfully, observe that you should now have 6 x SolutionStorefrontSite_ databases in SQL Server Management Studio.

11)
From https://github.com/Sitecore/Reference-Storefront/releases, download Sitecore.Reference.Storefront.for.SCpbCS.8.0.130.0.zip and extract the three files in the Packages folder (Adventure Works Images.zip, Sitecore.Reference.Storefront.Powered.by.CommerceServer.8.0.130.0.update, Sitecore.Reference.Storefront.Common.8.0.130.0.update).

  • First install Sitecore.Reference.Storefront.Common.8.0.130.0.update using the Sitecore UpdateInstallationWizard.aspx.
  • Then install Sitecore.Reference.Storefront.Powered.by.CommerceServer.8.0.130.0.update also using the Sitecore UpdateInstallationWizard.aspx.
  • Finally install the Adventure Works Images.zip (which essentially contains the product images) by going to the Sitecore Control Panel and selecting Install a Package.

12)
Rename the file C:\Sitecore\sc80rev150621\Website\MergeFiles\Merge.Commerce.Storefront.config to Merge.MVCSite.config.

Go back to the Powershell window and execute ./Deploy-Base-SC-Merge.ps1. This will merge web.config sections from the files in the MergeFiles folder into the main website web.config file.

13)
Open C:\Sitecore\sc80rev150621\Website\web.config, find the parameter siteName=”CSSolutionStorefrontSite” and change it to SolutionStorefrontSite (i.e. remove “CS”)

Also find

<add type=”publicKey” value=”registry:HKEY_LOCAL_MACHINE\SOFTWARE\CommerceServer\Encryption\Keys\CSSolutionStorefrontSite,PublicKey” />
<add type=”privateKey1″ value=”registry:HKEY_LOCAL_MACHINE\SOFTWARE\CommerceServer\Encryption\Keys\CSSolutionStorefrontSite,PrivateKey” />

and change these two values as well to remove “CS” in front of SolutionStorefrontSite.

Verify that you can browse to http://sc80rev150621/ and http://sc80rev150621/sitecore without getting any exceptions to ensure that the Commerce Server configuration has been correctly applied.

14)
Now we want to setup a fully compilable Storefront solution in Visual Studio that includes all the source files used.

  • Move the three folders CommonSettings, TDSCommon_Master and Project from C:\Deploy\Reference-Storefront-master\Storefront\Common to C:\Sitecore\sc80rev150621.
  • Move the three files (including the solution file) from C:\Deploy\Reference-Storefront-master\Storefront to C:\Sitecore\sc80rev150621.
  • Move all files, except web.config, from C:\Deploy\Reference-Storefront-master\Storefront\CS\CSF to C:\Sitecore\sc80rev150621\Website. Overwrite existing files.
  • Open the .sln file in a text editor (not Visual Studio!) and change the folder path references for the top four projects to be correct.
  • Create a new folder C:\Sitecore\sc80rev150621\Dependencies and copy all files from the C:\Sitecore\sc80rev150621\Website\bin folder into the Dependencies folder. Delete the two Sitecore.Reference.* files afterwards as they will conflict with the output of the build.
  • Open the solution in Visual Studio. Unless you have Team Development Suite installed, you will get a warning when you start it up that two projects are unsupported. You can ignore this for the purpose of this guide.
  • Now you get DLL hell. Don’t worry, they can all be fixed:
  • Update all the projects to use ASP.NET MVC 5 using NuGet by calling Install-Package Microsoft.AspNet.Mvc -Version 5.2.3 on all the projects.
  • For the Commerce.Storefront project, refresh DotNetOpenAuth using NuGet by calling Install-Package DotNetOpenAuth.
  • Delete the references to Sitecore.ContentSearch.SolrProvider and Sitecore.ContentSearch.SolrProvider.CastleWindsorIntegration as they are not necessary for the purpose of this guide.
  • Find the file CommerceServer.Core.Internal.ContentListHelper.dll in the folder C:\Windows\Microsoft.NET\assembly\GAC_64\CommerceServer.Core.Internal.ContentListHelper\v4.0_10.0.0.0__f5c79cb11734af7a from the GAC, copy it do the Dependencies folder and add a reference to it in the Commerce.Storefront project. This is to prevent the solution from (somehow, not sure why!) copying in the (wrong) 32 bit version of this assembly.
  • For the remaining missing assemblies, whether the system complain at compile time or at runtime, simply go through and add any missing ones from the Dependencies folder you created earlier. Most, if not all the exceptions you’ll get, will be caused by files that exist in the Dependencies folder but are missing from the bin folder.
  • Verify you can access http://sc80rev150621 with no exceptions thrown after having compiled the whole solution. You will still only see the original one-page sample site, which is okay for now.

15)
Do a full publish of the entire site.

16)
In your hosts file, add a new mapping for cs.reference.storefront.com to 127.0.0.1.

Also add this mapping as a binding in IIS for the sc80rev150621 website for port 80.

While you’re in IIS, also add a binding for SSL for the hostname cs.reference.storefront.com for port 443 to the sc80rev150621 website using a self-signed certificate. The checkout process of the Storefront site is running on HTTPS so this is necessary if you want to place an order (which you do!)

Verify you can go to http://cs.reference.storefront.com. However observe that there are no products shown.

17)
Index the site:

Click Sitecore > Control Panel > Indexing > Index Manager. Check sitecore_master_index and sitecore_web_index, then click Rebuild.

Refresh http://cs.reference.storefront.com and observe that products now are shown!

18)
Try placing an order and creating an account! This should work (it did for me!)

19)
Now you probably want to look this newly placed order up to ensure it has been stored correctly in the database. To do this, either have a look at the PurchaseTable in the SolutionStorefrontSite_transactions database through SQL Server Management Studio, or you can use the Commerce Server Windows application called Customers and Orders Manager which you can find in the Start Menu > Commerce Server 11 > Business Tools. To get this application to work, you need to perform the following additional steps:

This is the end of this (long) guide! Hopefully by now you’ve managed to setup the sample Sitecore Commerce Server Storefront site and can see how Sitecore envision we develop eCommerce sites in the future through Sitecore and Commerce Server. Having a working sample site certainly helps in understanding how many features work.

Let me know if you have any comments.

Advertisements

April 23, 2015

Installing Sitecore 8.0 and MongoDB in 10 minutes using Sitecore Instance Manager and PowerShell

Filed under: CMS,Sitecore — René @ 7:30 PM
Tags: , , ,

This quick guide demonstrates the fastest way to get up and running with Sitecore 8.0. It assumes you’ve never installed Sitecore 8 (or 7.5) before but have used Sitecore 7.2 or earlier, i.e. you don’t have MongoDB installed and configured.

Prerequisites:

Ensure you have the following applications installed:

  1. SQL Server 2014, SQL Server 2012, SQL Server 2008 R2 SP1, or SQL Express Editions of these databases installed
  2. IIS 8.5, IIS 8.0, IIS 7.5 or IIS 7.0 depending on which version of Windows you’re running.
  3. .NET Framework 4.5

Source: Sitecore 8 Installation Guide

Steps to install Sitecore 8

1)
Download this PowerShell script and execute it by right-clicking it and selecting Run with PowerShell. It’s a slightly modified version of the script found here, which automatically downloads MongoDB, installs it as a Windows Service and starts it – without any user intervention required at all. Don’t worry if you get a red error message at the top if you’re running it – it still works. While it’s downloading, it won’t show any progress indication. Depending on your internet connection, it will take 2-5 minutes to download, extract and configure MongoDB.

2)
Download the Sitecore Instance Manager (SIM). SIM is a key tool for managing the park of Sitecore instances. You can install, locate, maintain, reinstall or delete Sitecore products. When it has been configured, you can setup a new instance of any downloaded Sitecore version in 2 minutes with fewer than 10 clicks. Expand the zip file into a folder, e.g. “C:\SIM” and execute Sim.Tool.Exe. Follow the directions given by the tool in terms of giving it full access to a folder, specifying where your Sitecore license file exists, and what the login credentials are to your local SQL Server.

3)
Download the ZIP archive of the Sitecore site root for the latest version of Sitecore 8 using your Sitecore login. Save the .zip file in the repository folder specified in SIM.

4)
In SIM, select the icon Sites & Products and click Refresh Everything. This will make SIM pick-up the Sitecore zip file you just downloaded.

5)
In SIM, click Install Instance, and specify the site name you want, e.g. Sitecore8. Leave the remaining settings as they are. Click Next on the three next screens and finally click Install. SIM will then perform it’s magic, which includes expanding the zip file, copying in the license, setting up an IIS website, mounting databases in SQL Server and setting permissions where required. With an SSD drive, this takes less than 30 seconds for it to complete. When it’s done, select Open in Browser and then click Finish.  This should open the initial Sitecore landing page. Then navigate to /sitecore and login with “admin” and “b” and you should have a fully working Sitecore admin interface. Notice that this won’t mount any MongoDB databases. Instead Sitecore automatically creates those when you use it the first time.

6)
As you’ve now loaded both / and /sitecore, a session has been created for the visit by Sitecore in MongoDB. Akshay Sura has written a good post on how to use Robomongo, which let’s you inspect and modify the JSON documents in MongoDB. Opening it, you should now notice the following databases, which verifies that the Sitecore to MongoDB connection is working successfully.

Robomongo.

 

That’s it. Leave it comment if any of this doesn’t work for you.

UPDATE 24/04/2015:

The above guide should have helped you setup Sitecore 8 quickly. However, you might also want to consider the following tips before you commence using your new environment:

1)
Change your sessions to use your MongoDB as the session database. While this is obviously not required on a development workstation, it’s good practice to ensure that your development workstation is as similar to the production environment as possible, where you’d most likely want to use the new MongoDB session provider across multiple delivery servers. This link describes the two steps involved in doing this very well.

2)
Setup a 2nd reporting database in SQL Server. Sitecore continuously update the original Reporting database in SQL Server. It starts as soon as you launch Sitecore and it keeps the reporting database up to date with the most recent interactions, so long as the xDB is running. However, for various reasons, well described here, the reporting database might get out of sync or need a total rebuild. To do this, you would go to /sitecore/admin/RebuildReportingDB.aspx, but when you attempt to start the rebuild, you’ll get the error message “Connection string used by aggregation/historyTaskManager/ReportingStorage” as shown below:

Capture
The error message occurs as Sitecore actually requires that you have two reporting databases, so that one can still be available for reporting, while the other is rebuilding. To setup the secondary reporting database, stop the application pool, detach the reporting db from SQL Server Management Studio, copy the .mdf and .ldf files and rename the copied versions to .Secondary, attach the original reporting database again, then attach the new one as well. Finally, duplicate the name=”reporting” connection string to name=”reporting.secondary” and point it towards the new database. Then start the application pool again. If you go to /sitecore/admin/RebuildReportingDB.aspx, you should now be able to rebuild the reporting database.

Sitecore will automatically switch it’s reports over to using the secondary reporting database after it has been rebuilt (and back again to the primary one if you rebuild yet again).

October 10, 2014

Create Sitewide Sitecore Multivariate Tests

Filed under: Sitecore — René @ 11:52 AM
Tags: , , , ,

Sitecore ships with some fairly advanced multivariate testing out of the box. This is easy to use if you want to test a piece of content on a single page. Sitecore does this by automatically swapping out the DataSource of the particular component you’re testing.

However, what if you have a website with many, many pages, and they all share a common component, e.g. an area of advertisement shown in the middle of the page, and you want to test different content in this advertisement area across the site? Sitecore doesn’t provide any way to run a multivariate test across more than one page – it’s all focused on running a test on a single page.

In this post, I will demonstrate how we can custom build a text area, which is inserted on all pages on the site, and how we can execute a multivariate test across the site by reusing the code Sitecore itself uses to run multivariate tests. In fact, the three most central lines of code in this example comes from the Sitecore source code (thanks to Telerik JustDecompile, which is the best free decompiler I’ve used in a while!)

For the purpose of this example, I start with a blank Sitecore 7.2 instance and walk you through how to configure this. When you’ve done this, you should be able to extend it as you need.  The goal is to only configure and setup the multivariate test once across the site, regardless of how many pages you want to use it on, and not having to do it on every single page.

Here’s what you do:

1)

Download Sitecore 7.2 and setup a new local installation of Sitecore 7.2 (which this guide is tested with). This is really quick to do using the Sitecore Instance Manager.

2)

Create new templates based on the screenshot shown below:

Capture

The Variants field should be of type Multi-List with the following in the Source field:
query:ancestor-or-self::*[@@templatename=’Folder’]//*[@@templatename=’AdvertisementVariant’]

The Text field should be of type Single-Line Text.

3)

Create new content nodes based on these templates so you have the following structure.

Capture4

TestSettings is based on AdvertisementTestConfiguration template you just created.

Variant 1 and Variant 2 are based on AdvertisementVariant template.

4)

On the Variant 1 node, type “Variant 1” in the Text field.

On the Variant 2 node, type “Variant 2” in the Text field.

On the TestSettings node, in the Variants field, select the two variants you’ve created and add them to the Selected column (as shown below):

Capture5

 

5)

Create a new UserControl called SiteWideMultivariateTest.ascx and add the following code to it.

using System;
using System.Linq;
using Sitecore.Analytics;
using Sitecore.Data.Fields;
using Sitecore.Web.UI.WebControls;

namespace CustomWebsite
{
    public partial class SiteWideMultivariateTest : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lblText.Text = SelectVariantAndGetText();
        }

        public string SelectVariantAndGetText()
        {
            var subLayout = Parent as Sublayout;

            if (subLayout == null || subLayout.DataSource == null) return string.Empty;

            //get the Sitecore Item references in the Data Source
            var test = Sitecore.Context.Database.GetItem(subLayout.DataSource);

            //Get the Variants field that contains the variants to display
            var variantField = (MultilistField)test.Fields["Variants"];
            if (variantField == null) return string.Empty;

            var variants = variantField.GetItems();

            if (variants == null || !variants.Any()) return string.Empty;

            var visitorId = Tracker.CurrentVisit.VisitorId;
            var hashCode = visitorId.GetHashCode();

            //get a random number. The seed for the random generator is based on a bitwise exclusive-OR
            //of the hashcode of the VisitorId and the hashcode of the Sitecore "test" item that contains
            //the configuration of the test.
            //The result of this is that a new random number will be created per per visitor and per test
            var random = new Random(hashCode ^ test.ID.GetHashCode()).Next(0, variants.Count());

            var chosenVariant = variants[random];
            return chosenVariant.Fields["Text"].Value;
        }
    }
}

Notice the comment from line 36-39 explaining the magic that goes on. This is retrieved from decompiled Sitecore binaries and is the way Sitecore itself ensures that when you’re using the Sticky test strategy, the same visitor is shown the same variant for the same test regardless of how many times the page is viewed. We use the same mechanism here to ensure that the same visitor for the same test will be given the same variant for all pages this UserControl is inserted on.

6)

Create a new SubLayout in Sitecore called SiteWideMultivariateTest and references the newly created .ascx file.

7)

Add the newly created SiteWideMultivariateTest SubLayout to the Presentation Details on the standard values of the Sample Item (/Templates/Sample/Sample Item). Set it’s Data Source to the path of the Test you created earlier, e.g.

/sitecore/content/AdvertisementTest/TestSettings

8)

Create three pages (Page1, Page2, Page3) all based on the Sample Item template. Verify that their presentation details have the SiteWideMultivariateTest SubLayout already and that it’s DataSource is specified.

9)

Do a site wide Smart Publish and compile your new C# code.

10)

Go to /Page1 in your browser. It should now output either “Variant 1″ or Variant 2”. Go to /Page2 and /Page3 as well, and the same text should be outputted. Now clear you cookies and refresh either of those pages and keep doing this until you get the other variant. You should now again keep the same variant regardless of which of these three pages you view.

Conclusion

In this blog post I’ve demonstrated how you can run a multivariate test across multiple pages using the same technique Sitecore uses to execute it’s native multivariate tests. While this is obviously not the ideal way to execute a test, it is the only way I’ve found that allows me to execute a multivariate test across the whole site in a way that doesn’t depend on master pages.

This blog post doesn’t cover how you report on the effectiveness of the variants. You could fire an event to a web service when a user click on the advertisement, which would trigger a goal with an associated engagement value, or you could feed events into any Analytics platform.

June 9, 2014

Web Forms For Marketers’ Enroll in Engagement Plan Save Action not populating VisitorId

Filed under: Sitecore — René @ 9:57 AM
Tags: , ,

If you’ve used the Enroll in Engagement Plan save action in Web Forms For Marketers, you might have noticed that this action does not populate the VisitorId field in the AutomationStates table in the Sitecore Analytics database. This is illustrated below with a screenshot from the Analytics database of a newly enrolled Visitor. Notice that the VisitorId field is NULL.

Blog1

This is a problem if you expect to have the VisitorId available in a condition that’s attached to the state in the Engagement Plan. If the VisitorId field is empty, any condition with the word Visitor in the name will not work, as the condition won’t know the Visitor to use.

As the analytics visit is initiated when the page is loaded, the visitor already have a VisitorId and hence there’s no conceptual reason why you wouldn’t be able to associate a VisitorId with the entry in the AutomationStates table when the user completes the form and is enrolled in an Engagement Plan.

The steps below shows how you can address this issue by creating a new, different save action for Web Forms for Marketers that is a duplicate of the existing Enroll in Engagement Plan save action but also populates the VisitorId. I assume that you already have a sample Web Forms for Marketers form you’re using. If you don’t already have this, you should create one before following these steps.

1)

In your Visual Studio project, create a new class project called CustomWebsite. In this project, create a new class called EnrollInEngagementPlanWithVisitorId and paste in the code as shown below. This code is a decompiled version of the EnrollInEngagementPlan public class in the Sitecore.Forms.Custom.dll, with the lines 45-48 both inclusive added by me.

using Sitecore.Analytics;
using Sitecore.Analytics.Automation;
using Sitecore.Analytics.Automation.Data;
using Sitecore.Analytics.Data.DataAccess.DataSets;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Form.Core.Client.Data.Submit;
using Sitecore.Form.Core.Configuration;
using Sitecore.Form.Core.Submit;
using Sitecore.StringExtensions;
using System;

namespace CustomWebsite
{
    public class EnrollInEngagementPlanWithVisitorId : BaseSaveAction
    {
        public string EngagementState { get; set; }
        public string EnrollWhen { get; set; }

        public override void Execute(ID formid, AdaptedResultList fields, params object[] data)
        {
            if (!Tracker.IsActive)
                Tracker.StartTracking();

            if (Settings.IsAnalyticsEnabled && !string.IsNullOrEmpty(EngagementState) && fields.IsTrueStatement(EnrollWhen))
            {
                ID engagementStateId;
                if (!ID.TryParse(EngagementState, out engagementStateId))
                {
                    throw new InvalidOperationException(ResourceManager.GetString("NO_STATE_IN_ENGAGEMENT_PLAN_SELECTED"));
                }

                var externalUser = Tracker.Visitor.ExternalUser;
                if (string.IsNullOrEmpty(externalUser))
                {
                    throw new InvalidOperationException(ResourceManager.GetString("NO_SUCH_USER_EXISTS"));
                }
                if (!VisitorManager.AddVisitor(externalUser, engagementStateId))
                {
                    var str = ResourceManager.GetString("THE_VISITOR_CANNOT_BE_ENROLL");
                    var engagementPlanName = new object[] { GetEngagementPlanName(engagementStateId) };
                    throw new InvalidOperationException(str.FormatWith(engagementPlanName));
                }

                var dt = new VisitorDataSet.AutomationStatesDataTable();
                AutomationManager.Provider.GetVisitorAutomationState(dt, externalUser, engagementStateId.Guid);
                dt[0].VisitorId = Tracker.CurrentVisit.VisitorId;
                AutomationManager.Provider.UpdateAutomationStates(dt);
            }
        }

        private string GetEngagementPlanName(ID state)
        {
            Assert.ArgumentNotNull(state, "state");
            var item = StaticSettings.ContextDatabase.GetItem(state);
            return item == null ? state.ToString() : item.Parent.DisplayName;
        }

        public override ActionState QueryState(ActionContext context)
        {
            if (context.Tracking != null && Settings.IsAnalyticsEnabled && !context.Tracking.Ignore || context.Tracking == null && context.Form.IsAnalyticsEnabled)
            {
                return ActionState.Enabled;
            }
            return ActionState.Hidden;
        }
    }
}

These added four lines (45-48) essentially find the newly created engagement plan row in the AutomationStates table, and associates the VisitorId with this row.

2)
Find the node sitecore/system/modules/web forms for marketers/settings/actions/save actions/Enroll in Engagement Plan and duplicate it, calling the new node Enroll in Engagement Plan with VisitorId.

Change the Assembly and Class fields to be as specified in the screenshot below.

Blog2

3)
Open the form in the Web Forms for Marketers Form Designer, and add the newly created Enroll in Engagement Plan With Visitor Id save action. Be sure to specify which state in which engagement plan you want to add the user to. When you’ve done this, it should look like shown below, where the user is being added to the TestPlan Engagement Plan. Save these changes.

Blog3

4)
Smart publish the entire site.

5)
Complete the form again and notice as shown below that the entry in the AutomationStates table now have an associated VisitorId.

Blog4

That’s it!

You should now be able to enroll visitors in engagement plans when they complete a Web Forms for Marketers form AND subsequently use the Visitor related conditions Sitecore ships with out of the box against these visitors, as they now have an associated VisitorId.

June 3, 2014

How to Create Custom Sitecore Reports with C# Business Objects

Filed under: Sitecore — René @ 5:42 PM
Tags: , ,

Sitecore ships out of the box with some fairly advanced reporting capabilities. These are backed by the Web Edition of Stimulsoft’s Report Designer. This report designer can be used to create custom reports with custom SQL scripts against the Sitecore Analytics database as documented in the Sitecore manuals. This works perfectly out of the box and in most cases does the reporting job.

However, what if what you want to report on is not something that can easily be retrieved through the Sitecore Analytics database or through a database in general, yet you still want to present it through the Sitecore interface? This is not easy to accomplish as Sitecore have customized the Stimulsoft integration to always expect a SQL related data source. Using any other form of data source in your reports, e.g. a list of C# business objects, will not work. Using different data sources than SQL scripts for your reports might be necessary if you need to integrate multiple sources for reporting on your data.

Enter: the Sitecore Business Object Reports module which is now available on the Sitecore Marketplace (link)

Short overview
With this module, it’s very easy to create custom reports using Stimulsoft’s Report Designer, and then expose these reports to end users via links in the Sitecore Start Menu. With this module, data is fed into a report by using Stimulsoft’s concepts of Business Objects instead of forcing you to fetch data from the Sitecore Analytics database. This means that any C# returning data can be fed into a report and shown to a user.

Simplified, the process works like this:

  1. You create a separate assembly, with a single method “Execute” that returns an object. In this method, create a list of any type, and add some objects to this list and return this list.
  2. Create a report in Stimulsoft using the link in the Sitecore Start Menu this module provides. When creating the report, insert a business object data source and map it to the columns in your data.
  3. Create a new link in the Start Menu to feature this new report and specify the appropriate assembly and type name.
  4. Your business users will now be able to view the report simply by clicking on this link in the start menu, and the report is presented through the standard Stimulsoft Report Viewer component that can export to Excel and many other formats.

The module is tested with Sitecore 6.5 and 7.2, but should work anywhere in between as well as it does not use the new SPEAK interface.

Detailed Installation Instructions

  1. Ensure Flash Player is installed in your browser as Stimulsoft uses this
  2. Add a reference to all five Stimulsoft.*.dll files from the standard sitecore solution, if you’re not already referencing them.
  3. Install the Sitecore Package from the module’s page on Sitecore’ Marketplace
  4. This package installs files into sitecore modules\Shell\BusinessObjectReports. Ensure this folder is added to your Visual Studio solution so the code behind files are compiled.
  5. This package installs two links in the Start Menu. These links are inserted into the Core database. Both of these links needs to have their URL’s altered to use the host you’re using in your environment. Open the content editor, change to the core database, open sitecore/content/documents and settings/all users/start menu/left and for the two nodes “Business Object Report Designer” and “User Report”, change the host name in the “Message” field to be the host name you’re currently using.
  6. Copy the attached UserListLibrary.dll to the bin folder of your solution. This DLL contains a compiled version of some sample data that this project will feed into the Report. A source version of this is also available in the downloaded repository.
  7. Compile your solution, ensure it works, then open the two links in the start menu and enjoy!

Usage Instructions

When the module has been installed using the above installation instructions, open your Sitecore environment and observe two new links in the Sitecore start menu as shown below:

BusinessObject_1

The Business Object Report Designer is the designer that ships with this module, where you can create and configure new reports.

The User Report is an example report that is being fed data from a C# assembly.

 Viewing the sample report

If you click on the User Report, you should see the report shown below if your installation was successful. This demonstrate the module and its reports working. Notice that it simply displays sample data for five users.

BusinessObject_2

Creating a new custom report with C# Business Objects

In this example, we’ll create a new customer report to report on fictitious customers.

1)
Create a new C# Class Library called CustomerLibrary and generate some sample data to be featured in the report. This could e.g. look like shown below. Ensure the name of the assembly is the same as the name of the namespace, in this case CustomerLibrary.

using System.Collections.Generic;

namespace CustomerLibrary
{
    public class CustomerList
    {
        public static object Execute()
        {
            var list = new List<Customer>
            {
                new Customer {Name = "User One", Address = "High Street 1"},
                new Customer {Name = "User Two", Address = "High Street 2"},
                new Customer {Name = "User Three", Address = "High Street 3"},
                new Customer {Name = "User Four", Address = "High Street 4"},
                new Customer {Name = "User Five", Address = "High Street 5"}
            };
            return list;
        }

        public class Customer
        {
            public string Name { get; set; }
            public string Address { get; set; }
        }
    }
}

2)
Compile this new CustomerLibrary project and copy the DLL into your Sitecore website’s BIN folder.

3)
Open the Sitecore Content Editor, open the start menu and click on the new link Business Object Report Designer. Type in CustomerReport in the top text box field and click Create and Design as illustrated below.

BusinessObject_3

4)
The Stimulsoft Report Designer should now open. In the right hand side, click on the Dictionary tab, click the icon as shown below and select New Data Source.

BusinessObject_4

5)

A popup box is shown, where you should select Data From Business Objects.

6)

Fill in the values in the “New Data Source” dialogue as shown below. This will create a data source that expects data to be in a certain format for the report.

BusinessObject_5

For simplicity, keep the top three fields (Name in Source, Name and Alias) the same. The value you enter here you’ll need to reference later.

Click the button indicated in the red square above twice and specify the Alias, Name in Source, and Name for each of them. They should match the name of the property in the C# object exactly. In this example, create one called Name and one called Address. When you’re done, the screen should look like shown above. Click OK.

7)
Now you’ll need to create a report that pulls data from the data source you just created. Click the icon shown in the screenshot below, select New, then New Report with Wizard.

BusinessObject_6

8)
In the first dialogue, select the Customers data source as shown below.

BusinessObject_7

9)
In the next dialogue, select the Name and Address fields as shown below.

BusinessObject_8

Leave all remaining values as they are for the remaining steps and finish the wizard. The middle of the report should now look like shown below:

BusinessObject_9

10)
Save the report.

11)
Click the top left button and select Exit.

12)
In the Business Object Report Designer, in the Test Report section, select the new CustomerReport.mrt file and fill in the values as shown below.

BusinessObject_10

The Stimulsoft Name And Alias field needs to match the name and alias given to the data source in the Stimulsoft Report Designer when this data source was created.

Click Test Report. You should now see the report with the data being successfully pulled in from the Class Library as shown below:

BusinessObject_12

13)

Last step is to ensure a business user can access this customer report without having to put in technical details as an assembly name.

  1. Switch to the Core database
  2. Open the content editor and duplicate the node UserReport in sitecore/content/documents and settings/all users/start menu/left and call the new node CustomerReport.
  3. In the Display Name field, change the value to Customer Report.
  4. In the Message field, change the variables shown in bold below:
  5. RunExternal(\”http://YOURHOST/sitecore modules/Shell/BusinessObjectReports/SitecoreBusinessObjectReportViewer.aspx?Report=CustomerReport.mrt&AssemblyName=CustomerLibrary&TypeName=CustomerLibrary.CustomerList&NameAndAlias=Customers\”, \”\”, \”Applications/32×32/navigate_right2.png\”, \”Customer Report\”)
  6. Switch back to the Master database
  7. Open the new link Customer Report in the Start Menu and the report should successfully be shown, as shown below:BusinessObject_13

 

 

You have now successfully created a custom report with custom, non SQL based data, and exposed this report to your business users through the Stimulsoft Report Viewer that ships with Sitecore, so your business users can export the data as required. This could further be extended with filters and sorting to if desired.

Interested? Then download the module and/or the source code here from the Sitecore marketplace.

June 1, 2014

Add the Current Visitor to an Engagement Plan on Page Load

Filed under: Sitecore — René @ 4:24 PM
Tags: , , ,

Ever had to add the current visitor to an engagement plan when a particular page is loaded? Well, here’s how in five simple steps!

This can be useful e.g. if you in an engagement plan want to track how many people view a particular page that contains a Web Forms For Marketers form, even though they might never interact with the form. This would be useful to be able to determine how easy the form is to understand. If people never interact with the form at all although they see it, something would be wrong with the form.

The steps to be able to add the current visitor to an engagement plan are shown below, starting from the custom code necessary and working the way up through the Sitecore layers.

Step 1: Create a custom action

Create a new C# class with the following code:

using System;
using System.Collections.Generic;
using Sitecore.Analytics;
using Sitecore.Analytics.Automation.Data;
using Sitecore.Analytics.Data.DataAccess;
using Sitecore.Data;
using Sitecore.Rules;
using Sitecore.Rules.Actions;
using Sitecore.Form.Core.Configuration;

namespace CustomWebsite
{
    public class AddVisitorToEngagementPlan<T> : RuleAction<T> where T : RuleContext
    {
        public string ItemId { get; set; }

        public override void Apply(T ruleContext)
        {
            if (!Tracker.IsActive)
                Tracker.StartTracking();

            if (!Settings.IsAnalyticsEnabled || string.IsNullOrEmpty(ItemId)) return;

            var engagementPlanState = Sitecore.Context.Database.GetItem(ID.Parse(ItemId));
            if (engagementPlanState.TemplateID != ID.Parse("8CE2707A-3742-4A89-933B-065E5BE02BC9")) return;

            var engagementPlan = engagementPlanState.Parent;

            var visitor = Tracker.Visitor;
            var visitorLoadOption = new VisitorLoadOptions { Options = VisitorOptions.AutomationStates };
            visitor.Load(visitorLoadOption);

            if (Tracker.Visitor.DataSet.AutomationStates.Count > 0) return;

            AutomationManager.Provider.CreateAutomationStatesFromBulk(new List<Guid> { Tracker.CurrentVisit.VisitorId }, engagementPlan.ID.Guid, engagementPlanState.ID.Guid);
        }
    }
}

This action expects as input a particular engagement plan state, and will enroll the current visitor into this state when executed.

Step 2: Create new Action node

Create a new node in Sitecore based on the Action template. In Sitecore 7.1 and 7.2 this action should be created here:

/sitecore/system/settings/rules/definitions/elements/system

Call it AddVisitorToEngagementPlan.

Complete the following two fields on the new node:

Text:
Add Visitor To Engagement Plan State: [ItemId,Tree,root={4497A9BE-0A00-4EE4-9AE0-50D6CBB4FAB2}&resulttype=Id&setRootAsSearchRoot=true,ItemId]

Type:
CustomWebsite.AddVisitorToEngagementPlan, CustomWebsite

If you have changed the assembly name and/or type from the code snipped provided in Step 1, you must change it in the above type reference as well. The root GUID shown above is the item GUID of the “Engagement Plans” folder in the Marketing Center. This ensures that users only can pick items among that node and its children.

Step 3: Create an engagement plan

In the Marketing Center, create a new engagement plan for the purposes of this test. Call it Test. Ensure you Deploy the plan on the Review tab.

Create a single state on the plan, so you have a state you can enroll your visitors in. Call it My Initial State. An example of this is shown below:

Untitled

Step 4: Create new goal

In the Marketing Center, create a new goal called AddVisitorToMyInitialState. Ensure you Deploy the goal.

In the Rules section of this goal, click Edit Rule, and configure it as shown below:

Capture

When this goal is executed, the rule will be triggered. Because the condition of the rule is “where true”, it will always execute it’s action, which is the new Action you just created in step 2.

Step 5: Associate goal with page

The last step remaining is to trigger the goal on a particular page. As shown below, select a content item in the Content Editor, select the Analyze tab, select Goals and tick AddVisitorToMyInitialState.

Goal

Publish all your changes, go to the page you added the goal to, and this will add the visitor to the specified engagement plan state. This can be confirmed by opening the engagement plan in the Supervisor mode as shown below.

supervisor

That’s it! This is tested successfully on both Sitecore 7.1 and 7.2, but should work fine on older versions as well, although the Action node has to be created in a different path.

 

May 26, 2014

Sitecore Engagement Plans not working?

Can’t get Sitecore’s Engagement Plans to work? I struggled with this for a while…

Sitecore’s Engagement Plans lays a very powerful foundation for using the suite of Sitecore tools and features to perform Marketing Automation. You can combine Engagement Plans with, say, Web Forms for Marketers and
Email Campaign Manager and track, capture and engage with users across multiple engagements with the same platform.

However, when you perform a default installation of Sitecore CMS and DMS, and setup your first engagement plan, nothing will ever happen. Say you:

  1. configure two states with a condition between
  2. import a single user into the first state
  3. set a condition to trigger after 1 minute that will move this user to the second state.

If you do this, save and publish, the user will never be moved to the second state.

Why not?

Because you need to tell Sitecore the name of the machine that should run the recurring task that checks the WakeupDateTime field in the AutomationStates table in the Sitecore Analytics database whether any visitors/users needs to be processed.

To do this, open App_Config/Include/Sitecore.Analytics.config, find the property Analytics.Automation.MachineName and set it to the name of your machine. This is illustrated below.

AutomationPlan

Notice that this field is CASE SENSITIVE and should not include the domain suffix if your computer is on a corporate network. I recommend opening a command prompt and typing in “echo %COMPUTERNAME%”, and use that exact value as the parameter. This worked for me.

In a production environment, you’ll want to make sure that this is the name of the internal authoring server that is to be responsible for running the workflow logic to ensure users are moved between states as configured.

May 24, 2014

Adding Personalization Rules without modifying files

Filed under: Sitecore — René @ 1:55 PM
Tags: , , , ,

Recently I had to investigate for a client if it would be possible to create a personalization rule in Sitecore that would determine whether the current URL has a specific value in a specific query string parameter, but without making any changes to any files on the server. That meant it would be impossible to create a new personalization rule for the Rule Editor as that would have to reference a new or updated DLL which would require changes on the server.

Instead, I set out to explore if this was possible without any changes on the server, and found out that it was. In fact, it’s pretty simple, but pretty hard to get working. The steps are outlined below and are successfully tested with Sitecore 7.2

Step 1:

Create a node in Sitecore based on the Script template, and enter in the following content in the Code field:

namespace Sitecore { public class DefaultClass { public bool DefaultMethod(Sitecore.Data.Items.Item value) { return Sitecore.Context.RawUrl.ToLower().Contains(“somevalue”); } } }

This is illustrated in the screenshot below.

Notice that you don’t seem to be able to retrieve the current URL (and query string parameters) from HttpContext.Current.Request.QueryString, but Sitecore.Context.RawUrl does work.

Script in Sitecore

 

Step 2:

As shown below, use the rule where calling the specific script returns true and select the script created in Step 1.

Capture2

Step 3:

Sitecore caches these rules in the ScriptFactory, so performance shouldn’t be impacted by doing this. The cache key for an item being cached is the ID of the script item you created in Step 1. This means you need to ensure that when you update the item with new code in the Content Editor, the ScriptFactory cache (different to the HTML cache that is normally cleared on publish) needs to be cleared. Running on normal publish does not seem to do the trick.

However, it would appear there’s a bug in Sitecore that does not do this automatically, so you need to add a separate condition, as shown below:

Capture3

The “Clear Script Cache” is already there in the default installation and specifies what should happen when an item is saved in Sitecore. This is triggered by one of the default pipelines in the item:save event in web.config. However, the line highlighted in the red box above appears to be missing, which I would claim is a bug in Sitecore. Adding this in, i.e. also clearing the script cache if the item template is of type “Script” will do the trick, and ensure the script cache is cleared every time you save the item in Sitecore.

Conclusion

Voila. You can now personalize any data source in Sitecore based on whether a query string parameter contains a particular value.

This means you can essentially run any C# based logic in a rule. Sitecore will compile this rule and store it in a memory based cache, for optimal performance.

While this practice is a bad idea from any sound architectural standpoint, it does provide flexibility in situation where this is required and code changes are not possible on a production environment.

Blog at WordPress.com.

%d bloggers like this: