HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Marketing and campaigns

Describes the campaign management functionality in Optimizely Customized Commerce 13.

This includes how to use the API for working with promotions (discounts) as part of a campaign.

Promotions (discounts) are available to end-users under Marketing in the Optimizely Customized Commerce user interface. Per definition, a campaign is a container for creating and applying promotions. A campaign is also a content type, supported by the content model in Optimizely.

The Campaign content type

Components mentioned here are available in the EPiServer.Commerce.Marketing namespace.

Customized Commerce provides one standard campaign type: SalesCampaign. This class is a basic content, which means it does not follow the normal publishing workflow of content. The class has the properties IsActive, ValidFrom, and ValidUntil, which control the status of the campaign.

This class can also restrict a campaign to one or more visitor groups through the property VisitorGroup, which supports the targeting of customer segments. Finally, the sales campaign has a RevenueGoal.

using EPiServer.Commerce.Catalog.ContentTypes;
    using EPiServer.Commerce.Marketing;
    using EPiServer.Commerce.Marketing.DataAnnotations;
    using EPiServer.Core;
    using EPiServer.DataAbstraction;
    using EPiServer.DataAnnotations;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace EPiServer.Commerce.Sample.Models.Campaigns
      {
        [ContentType(GUID = "530a7f07-8d12-4625-bda3-8e135a10b74d")]
        [AvailableContentTypes(Include = new[] { typeof (PromotionData) })] 
        public class SeasonalCampaign : SalesCampaign
        {
          [Display(Order = 12, GroupName = SystemTabNames.PageHeader, Prompt = "Hero Image")]
          public virtual ContentReference HeroImage { get; set; }
    
          [Display(Order = 13, GroupName = SystemTabNames.PageHeader, Prompt = "Banner Image")]
          public virtual ContentReference BannerImage { get; set; }
        }
      }

Use render templates

Campaign content uses normal rendering templates as described here. By default, only partial views are available for campaign content. To enable campaigns and pages, please see below.

using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using EPiServer;
    using EPiServer.Commerce.Marketing;
    using EPiServer.Core;
    using EPiServer.Framework.DataAnnotations;
    using EPiServer.Web.Mvc;
    using MyOptimizelySite.Models.Pages;
    using System.Web.Security;
    
    namespace MyOptimizelySite.Controllers
      {
        [TemplateDescriptor(Default = true)]
        public class CampaignPartialController : PartialContentController<SalesCampaign>
          {
            public ActionResult Index(SalesCampaign currentCampaign)
              {
                // Implementation of action view the page. 
                return View(currentCampaign);
              }
          }
      }

Example: The corresponding rendering view for displaying the campaign partial view.

@using EPiServer.Core
    @using EPiServer.Web.Mvc.Html
    
    @model EPiServer.Commerce.Marketing.SalesCampaign
    
    <h1>
        @Html.DisplayFor(m => m.Name)
    </h1>
    <h3>
        @Html.PropertyFor(m => m.Description)
    </h3>

    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using EPiServer;
    using EPiServer.Commerce.Marketing;
    using EPiServer.Core;
    using EPiServer.Framework.DataAnnotations;
    using EPiServer.Web.Mvc;
    using MyOptimizelySite.Models.Pages;
    using System.Web.Security;
    
    namespace MyOptimizelySite.Controllers
      {
        [TemplateDescriptor(Default = true)]
        public class CampaignPageController : ContentController<SalesCampaign>
          {
            public ActionResult Index(SalesCampaign currentCampaign)
              {
                // Implementation of action view the page. 
                return View(currentCampaign);
              }
          }
      }

Example: The corresponding rendering view for displaying the campaign page view.

@using EPiServer.Core
    @using EPiServer.Web.Mvc.Html
    
    @model EPiServer.Commerce.Marketing.SalesCampaign
    
    <h1>
        @Html.DisplayFor(m => m.Name)
    </h1>
    <h3>
        @Html.PropertyFor(m => m.Description)
    </h3>

Campaign content as pages

using EPiServer.Commerce.Marketing;
    using EPiServer.Core;
    using EPiServer.DataAbstraction;
    using EPiServer.DataAnnotations;
    using EPiServer.Web.Routing;
    using System.ComponentModel.DataAnnotations;
    
    namespace EPiServer.Commerce.Sample.Models.Campaigns
      {
        [ContentType(GUID = "530a7f07-8d12-4625-bda3-8e135a10b74d")]
        [AvailableContentTypes(Include = new[] { typeof (PromotionData) })] 
        public class SeasonalCampaign : SalesCampaign, IRoutable
          {
            [Display(Order = 12, GroupName = SystemTabNames.PageHeader, Prompt = "Hero Image")]
            public virtual ContentReference HeroImage { get; set; }
    
            [Display(Order = 13, GroupName = SystemTabNames.PageHeader, Prompt = "Banner Image")]
            public virtual ContentReference BannerImage { get; set; }
    
            public virtual string RouteSegment { get; set; }    
          }
      }

    using EPiServer.Core;
    using EPiServer.DataAbstraction;
    using EPiServer.Framework;
    using EPiServer.Framework.Initialization;
    using EPiServer.ServiceLocation;
    using EPiServer.Web.Routing;
    using EPiServer.Web.Routing.Segments;
    using System.Linq;
    using System.Web.Routing;
    
    namespace EPiServer.Commerce.Sample.Business.Initialization
      {
        /// <summary>
        /// Initialization module to handle the initialization of Commerce.
        /// </summary>
        [ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]
        [InitializableModule]
        public class CampaignInitalization : IConfigurableModule
          {
            /// <summary>
            /// Initializes Commerce using the specified context.
            /// </summary>
            /// <param name="context">The context.</param>
            public void Initialize(InitializationEngine context)
              {
                EPiServer.Global.RoutesRegistered += Global_RoutesRegistered;
              }
    
            private void Global_RoutesRegistered(object sender, RouteRegistrationEventArgs e)
              {
                RegisterRoutes(RouteTable.Routes);
              }
    
            private static void RegisterRoutes(RouteCollection routes)
              {
                // Route for editing commerce content (which has a root not connected to the global root)
                MapCampaignRoute(routes,
                    name: "campaignroot",
                    url: "Campaigns/{language}/{nodeedit}/{partial}/{action}",
                    defaults: new { action = "index" });
              }
    
            private static void MapCampaignRoute(RouteCollection routes, string name, string url, object defaults, object constraints = null)
              {
                var contentRootService = ServiceLocator.Current.GetInstance<ContentRootService>();
                var root = ServiceLocator.Current.GetInstance<IContentLoader>()
                    .GetItems(contentRootService.List(), new LoaderOptions())
                    .SingleOrDefault(x => x.Name.Equals("SysCampaignRoot"));
                var segmentRouter = ServiceLocator.Current.GetInstance<IUrlSegmentRouter>();
                segmentRouter.RootResolver = (sd) => root.ContentLink;
    
                var parameters =
                    new MapContentRouteParameters
                      {
                        UrlSegmentRouter = segmentRouter,
                        BasePathResolver = null,//Use Cms default
                        Direction = SupportedDirection.Both,
                        Constraints = constraints
                      };
    
                routes.MapContentRoute(
                    name,
                    url,
                    defaults,
                    parameters);
              }
    
            public void Uninitialize(InitializationEngine context)
              {
                // Uninitialize catalog content version
             }
    
            public void ConfigureContainer(ServiceConfigurationContext context)
              {
              }
          }
      }

Related blog post: Filter your commerce campaigns for access by Jeroen Stemerdink