6

I am trying to get all personalization set in a given page from a RenderingController context.

Any idea?

public ActionResult GetPersonalizationRule()
{
    var contextItem = Sitecore.Context.Item;           
    // Code to get all personalizations
    return View();
}

5 Answers 5

10

You can get the personalization from the renderings field. If you open an item that contains personalization you will notice on the renderings field in Raw mode something like this:

<rls><ruleset><rule uid="{088B27BA-3E2E-4928-9F67-3951C7C0F112}" s:name="test"><conditions><condition uid="7B0698159A914755B99BE5A5D6A0786D" s:id="{8A9B001F-FB59-4F0F-B3F3-C6C5360ED451}" s:Now="20170728T180300Z" /></conditions><actions><action uid="239294CA205E4A0CBD648A3C07037E89" s:id="{25F351A1-712D-45F8-857D-8AD95BB2ACE9}" /></actions></rule><rule uid="{00000000-0000-0000-0000-000000000000}" s:name="Default"><conditions><condition uid="A33C959CAB4E4AC783FB25888B10A759" s:id="{4888ABBB-F17D-4485-B14B-842413F88732}" /></conditions><actions /></rule></ruleset></rls>

This is the personalization rules set on the field with an XML format.

So the first thing you need to do is loop and filter which renderings you want to check for personalization.

this will be something like this(haven't tested the code but should work)

Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(Sitecore.Context.Device);

I'll add the remaining code shortly but this should point you to the right direction

3
  • 1
    That worked! Thank you. I added the following to filter the rendering with personalization: var renderingsWithPersonalization = renderings.Where(r => r.Settings.Rules.Count > 0).ToList();
    – João Neto
    Jul 11, 2017 at 18:36
  • Yeah I was about to update with the rules code pretty similar to what you just sent but since you done it I won't :) glad it worked out João
    – Diego
    Jul 11, 2017 at 18:39
  • This won't be accurate unless you run it after all personalization has been applied which is not in the context noted in the question. As far as I know you have to run this logic in the mvc.RequestEnd pipeline to get accurate results. Dec 11, 2019 at 14:02
5

Using Sitecore PowerShell Extensions, you can run a report to find all item renderings with personalization rules. Hopefully this will be included in SPE 5.1.

Report

$database = "master"
$root = Get-Item -Path (@{$true="$($database):\content\home"; $false="$($database):\content"}[(Test-Path -Path "$($database):\content\home")])
$settings = @{
    Title = "Report Filter"
    ShowHint = $true
    OkButtonName = "Proceed"
    CancelButtonName = "Abort"
    Description = "Filter the results for item renderings with personalization rules."
    Parameters = @(
        @{
            Name="root"
            Title="Choose the report root"
            Tooltip="Only items from this root will be returned."
            Root="/sitecore/content/"
        }
    )
    Icon = [regex]::Replace($PSScript.Appearance.Icon, "Office", "OfficeWhite", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
}

$result = Read-Variable @settings
if($result -ne "ok") {
    Exit
}
$items = @($root) + @(($root.Axes.GetDescendants()))

function HasRuleOnRendering {
    param(
        [Sitecore.Layouts.RenderingDefinition]$Rendering
    )

    $hasRules = $false

    if($rendering -and ![string]::IsNullOrEmpty($rendering.Rules) ) {
        $hasRules = $true
    }

    $hasRules
}

$renderingLookup = @{}
$reportItems = [System.Collections.ArrayList]@()
Write-Host $items.Count
foreach($item in $items) {
    $renderings = Get-Rendering -Item $item -FinalLayout
    foreach($rendering in $renderings) {
        if((HasRuleOnRendering -Rendering $rendering)) {
            $renderingName = $rendering.ItemId.ToString()
            if($renderingLookup.ContainsKey($rendering.ItemId)) {
                $renderingName = $renderingLookup[$rendering.ItemId]
            } else {
                $renderingName = Get-Item -Path "master:" -ID $rendering.ItemId | Select-Object -Expand Name
            }

            $datasource = $rendering.Datasource
            if([ID]::IsID($datasource)) {
                $datasource = Get-Item -Path "master:" -ID $rendering.Datasource | Select-Object -Expand ItemPath
            }

            $reportItem = [PSCustomObject]@{
                "Icon" = $item.Appearance.Icon
                "ItemPath" = $item.Paths.Path
                "Rendering" = $renderingName
                "Datasource" = $datasource
            }
            $reportItems.Add($reportItem) > $null
        }
    }
}

if($reportItems.Count -eq 0) {
    Show-Alert "There are no items matching the specified criteria."
} else {
    $reportProps = @{
        Title = "Renderings with Personalization Report"
        InfoTitle = "Renderings with personalization rules"
        InfoDescription = "This report provides details about which items have renderings configured with personalization rules."
    }

    $reportItems | Show-ListView @reportProps
}
Close-Window
1
0

Below line gives all list of rules on each rendering but not evaluated one:

var renderingsWithPersonalization = renderings.Where(r => r.Settings.Rules.Count > 0).ToList(); 
0

Below lines gives all the exposed rules on the page item:

var personalization = Tracker.Current.Interaction.CurrentPage.Personalization;
var exposedRules = personalization.ExposedRules;
0
0

I had the same requirement. The below line of code is working for me to get renderings and its rules count properly.

 var item = Sitecore.Context.Item;

        var personalization = Tracker.Current.Interaction.CurrentPage.Personalization;

        if (personalization == null)
        {
            return null;
        }

        var exposedRules = personalization.ExposedRules;
       
        var renderings = item.Visualization.GetRenderings(Sitecore.Context.Device, false);

        if (renderings == null)
        {
            Sitecore.Diagnostics.Log.Info("No renderings for this page", this);

            return null;
        }

        var renderingsWithRules = renderings.Where(x => x.Settings.Rules.Count > 0).ToList();

        if (!renderingsWithRules.Any())
        {
            Sitecore.Diagnostics.Log.Info("No components with personalization rules", this);

            return "no-personalization";
        }

        var builder = new StringBuilder();

        var count = 0;

        foreach (var component in renderingsWithRules)
        {

            var componentName = GetComponentAliasName(component.RenderingItem.Name.ToLower());

            var ruleContext = new ConditionalRenderingsRuleContext(renderingsWithRules, component);

            var pnum = 0;

            foreach (var rule in component.Settings.Rules.Rules)
            {

                if (rule.Evaluate(ruleContext))
                {
                    builder.Append($"{componentName + pnum}");
                    break;
                }

                pnum++;
            }

            count++;

            if (renderingsWithRules.Count() != count)
            {
                builder.Append("_");
            }

        }

        return builder.ToString();
    }
1
  • 1
    Thanks for joining Sitecore stack exchange. This answer does not provide much feedback. Can you please add more code on how your determined what personalizations were in place on the page.
    – Chris Auer
    Nov 10, 2020 at 3:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.