How do I determine which personalized blocks will be shown in a content area

  • Page Owner: Not Set
  • Last Reviewed: 2021-07-12

This issue arose when I was using the the number of blocks in a content area to determine bootstrap column numbers. The problem that was discovered was when you are using personalization you might have 4 blocks in a personalization group and 2 blocks outside of a personalization group, you would only ever have 3 blocks visually shown to the user but the content area still has 6 blocks in it.


Answer

Here is how I solved this issue.

In order to access visitor groups current being applied to a content area item you can use the AllowedRoles property to get a list of GUID's. For each GUID in that allowed roles property I check whether or not the current user will be allowed to see the block using this extension method:

public static bool IsMatchCriteria(string guid)
{
   var visitorGroupGuidId = new Guid(guid);
   var visitorGroupRepository = ServiceLocator.Current.GetInstance<IVisitorGroupRepository>();
   var user = HttpContext.Current.User;

   var vgHelper = new VisitorGroupHelper();
   var visitorGroup = visitorGroupRepository.Load(visitorGroupGuidId);
   return vgHelper.IsPrincipalInGroup(user, visitorGroup.Name);
}

This will allow you to count which block in a personalized group is going to be shown to the user.

The problem you're going to run into next is if an editor has set a fallback block in case no block in the personalized group will be shown to the current user. These fallback blocks do not have any rolls in their AllowedRoles property so it would be easy to assume they are just regular blocks with no personalization associated with them.

Here is my full extension method:

public static int ContentAreaCountWithPersonalization(this ContentArea contentArea) { 

if (!contentArea.HasValue()) 
    return 0;

var count = 0;
var personalizationMatches = new List<string>();

foreach(var block in contentArea.Items)
{
  if (block.AllowedRoles.HasValue())
  {
     if (block.AllowedRoles.Any(x => IsMatchCriteria(x)))
     {
          count++;
          if (block.ContentGroup.HasValue())
          {
             personalizationMatches.Add(block.ContentGroup);
          }
      }
   }
   else if(
   !block.AllowedRoles.HasValue() 
   && block.ContentGroup.HasValue() 
   && personalizationMatches.HasValue() 
   && personalizationMatches.Any(x => x == block.ContentGroup))
   {
       continue;
   }
   else 
   {
       count++;
    }
 }
  return count; 
}

Whenever a content area item is apart of a personalization group there is a property called ContentGroup that will have an identifier that will be the same for all blocks in that group. I used this to track when a block in a Content Group had a matching visitor group and would be shown to a user. If I ran into a block with no Allowed Roles but was apart of a Content Group and a block in that content group would be shown to the user I can safely assume this block could be skipped from my count.