Rendering Optimizely Experiences: How OptimizelyComposition, OptimizelyGridSection, and OptimizelyComponent Fit Together

If you’ve started building with the Optimizely Content JS SDK, you’ve probably run into three similarly-named rendering components and wondered which one does what: OptimizelyComposition, OptimizelyGridSection, and OptimizelyComponent. Here’s a brief overview of each.

  • Optimizely Composition

OptimizelyComposition is the top-level renderer for an experience. You use it on any content type with baseType: '_experience' and it walks the composition tree and delegates each part to the right renderer. Think of it as the entry point that turns the visual builder’s structure into rendered output.

  • Optimizely Grid Section

OptimizelyGridSection renders a single section and its grid layout of rows and columns. Sections are the containers inside a composition, and this component arranges their child elements into the grid.

  • Optimizely Component

OptmizelyComponent renders an individual block at the leaf level of the tree. It resolves a content type to its registered React component.

The diagram below brings all three together under one umbrella.

Putting It All Together: Experience → Section → Component

I’ve added an experience content type in Optimizely, shown below, with a single field inside it named PageHeading.

Next, I created a section type to be added inside experiences built from the experience type above.

Next, I created a Banner Block that sits inside the section type above.

Note: For the Banner Block to be allowed inside the section type, you need to enable the Element checkbox under the Settings tab, as shown below.

Once the content types are modeled, we can create an experience page in the visual builder, as shown below, and add the section type created above inside it. The section contains a single row with two columns, and a Banner Block is added to each column.

Wiring Up the Components

With the content types modeled, let’s look at the code for each component in the head application.

The content type modelled in Optimizely SAAS are pulled into the Head app through running the below command.

npx @optimizely/cms-cli config pull --output ./src/content-types --group

With the models pulled into the file system, let’s add the code for each of the components above.

  1. Create experience type component inside ‘src/components/experience/{{ExperienceType}}.tsx’ file.
import type { ContentProps } from '@optimizely/cms-sdk';
import { getPreviewUtils, OptimizelyComposition } from '@optimizely/cms-sdk/react/server';
import type { CKExperienceTypeCT } from '@/src/content-types/experience/CKExperienceType';

type CKExperienceTypeContent = ContentProps<typeof CKExperienceTypeCT>;

type Props = {
  content: CKExperienceTypeContent;
  displaySettings?: Record<string, string | boolean>;
};

export default function CKExperienceType({ content }: Props) {
  const { pa } = getPreviewUtils(content);

  return (
    <article className="mx-auto w-full max-w-6xl px-6 py-12">
      {content.composition?.nodes && (
        <div className="flex flex-col gap-8">
          <OptimizelyComposition nodes={content.composition.nodes} />
        </div>
      )}
    </article>
  );
}

Leave a comment