HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunitySubmit a ticketLog In

Personalize content with a headless approach

Describes how to personalize content using a headless approach for content recommendations through the Optimizely Content Delivery API (version 2).



This section applies only if you are still using Content Delivery Api v2.x.x. For users using Content Delivery API v3.x.x, see Breaking change in v3.

How do you add content personalization to a headless solution where the tracking does not hit a controller in the presentation layer? You can use a headless approach for content recommendations through the Optimizely Content Delivery API. You must implement compatible tracking and calls to the recommendation API to do this. See the Optimizely Tracking Developer Guide.

In a headless scenario, you can also customize the DefaultContentModelMapper and replace it with your own. See Customize data returned to clients and Serialization.

Example: Customizing DefaultContentModelMapper

You can manipulate with personalization by customizing the DefaultContentModelMapper.

  1. Create a class where your CustomContentModelMapper inherits from DefaultContentModelMapper. Register it with ServiceConfiguration and in DependencyResolverInitialization (this is an example from an Alloy site).

    public void ConfigureContainer(ServiceConfigurationContext context) {
      //Implementations for custom interfaces can be registered here.
      context.ConfigurationComplete += (o, e) => {
        //Register custom implementations that should be used in favour of the default implementations
        context.Services.AddTransient<IContentRenderer, ErrorHandlingContentRenderer>()
          .AddTransient<ContentAreaRenderer, AlloyContentAreaRenderer>()
          .AddTransient<IContentModelMapper, CustomContentModelMapper>();
  2. With CustomContentModelMapper

    [ServiceConfiguration(typeof (IContentModelMapper), Lifecycle = ServiceInstanceScope.Singleton)]
    public class CustomContentModelMapper: DefaultContentModelMapper {
      public CustomContentModelMapper(IContentTypeRepository contentTypeRepository, ReflectionService reflectionService, IContentModelReferenceConverter contentModelService, IUrlResolver urlResolver, IEnumerable<IPropertyModelConverter> propertyModelConverters): base(contentTypeRepository, reflectionService, contentModelService, urlResolver, propertyModelConverters) {}
      public override ContentApiModel TransformContent(IContent content, bool excludePersonalizedContent = false, string expand = "") {
        var personalization = System.Web.HttpContext.Current.Request.Params["personalization"];
        return base.TransformContent(content, string.IsNullOrWhiteSpace(personalization) ? excludePersonalizedContent : Boolean.Parse(personalization), expand);

This way, you can take advantage of personalization parameters in your request.



The DefaultContentModelMapper is currently marked as internal, so there is a risk of unadvertised breaking changes when customizing this.