HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Marketing and campaigns

Describes the campaign management functionality in Optimizely Commerce Connect.

You can use the API in Optimizely Commerce Connect for working with promotions (discounts) as part of a campaign.

Promotions (discounts) are available to end-users under Marketing in the Commerce Connect 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

The components mentioned here are available in the EPiServer.Commerce.Marketing namespace.

Commerce Connect 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 campaign's status.

This class can also restrict a campaign to one or more visitor groups through the property VisitorGroup, which supports targeting 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; }
        }
      }

Usr 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 EPiServer.Commerce.Marketing;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Web.Mvc;

namespace MyOptimizelySite.Controllers
{
    [TemplateDescriptor(Default = true)]
    public class CampaignPartialController : PartialContentComponent<SalesCampaign>
    {
        protected override IViewComponentResult InvokeComponent(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