Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Work with DAM assets

Provides Optimizely CMS (SaaS) helper functions for rendering DAM images with automatic preview tokens, responsive srcset, and alt text handling.

When you enable the DAM integration in your CMS (SaaS) instance, you get helper functions for working with images, media, and files from Optimizely's Content Marketing Platform (CMP). These utilities handle preview tokens, generate responsive image markup, and manage alt text automatically.

📘

Note

These utilities only work when you enable DAM assets in your Optimizely Graph. Check with your CMS administrator if you are not sure whether the integration is active.

The SDK includes the following helpers:

  • damAssets() – Returns pre-configured helpers for the content property.
  • getSrcset() – Builds responsive srcset strings from renditions.
  • getAlt() – Pulls alt text from assets (with fallback support).

Use damAssets()

Use damAssets() to access DAM helper functions for a content instance. This function automatically applies preview tokens when editors view content in preview mode.

The damAssets() function returns:

  • getSrcset() - Generates responsive srcset strings
  • getAlt() - Retrieves alt text with fallback support
  • isDamImageAsset() - Type guard for image assets
  • isDamVideoAsset() - Type guard for video assets
  • isDamRawFileAsset() - Type guard for file assets
  • getDamAssetType() - Returns asset type as a string
  • isDamAsset() - Validates any DAM asset
import { damAssets } from '@optimizely/cms-sdk';

export default function HeroComponent({ content }) {
  const { src } = getPreviewUtils(content);
  const { getSrcset, getAlt } = damAssets(content);

  return (
    <img
      src={src(content.heroImage)}
      srcSet={getSrcset(content.heroImage)}
      sizes="(max-width: 768px) 100vw, 50vw"
      alt={getAlt(content.heroImage, 'Hero image')}
    />
  );
}

Generate responsive images with getSrcset()

getSrcset() builds a valid srcset attribute from the renditions defined on a DAM asset.

  • Filters out duplicate widths (keeps the first one).
  • Adds preview tokens automatically in edit mode.
  • Returns undefined if there are no renditions.
import { damAssets } from '@optimizely/cms-sdk';

export default function ProductImage({ content }) {
  const { src } = getPreviewUtils(content);
  const { getSrcset } = damAssets(content);

  return (
    <img
      src={src(content.productImage)}
      srcSet={getSrcset(content.productImage)}
      sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
      alt="Product image"
    />
  );
}

The generated srcset appears as follows:

https://example.dam.optimizely.com/image1.jpg 100w,
https://example.dam.optimizely.com/image2.jpg 500w,
https://example.dam.optimizely.com/image3.jpg 1000w

getAlt()

getAlt() resolves alt text using the following priority order:

  1. Check the asset's AltText property.
  2. Use your fallback text.
  3. Use an empty string for decorative images.
import { damAssets } from '@optimizely/cms-sdk';

export default function ImageComponent({ content }) {
  const { src } = getPreviewUtils(content);
  const { getAlt } = damAssets(content);

  return <img src={src(content.image)} alt={getAlt(content.image)} />;
}

Provide fallback alt text

import { damAssets } from '@optimizely/cms-sdk';

export default function BannerComponent({ content }) {
  const { src } = getPreviewUtils(content);
  const { getAlt } = damAssets(content);

  return (
    <img
      src={src(content.bannerImage)}
      alt={getAlt(content.bannerImage, 'Marketing banner')}
    />
  );
}

For decorative images

If no alt text exists on the asset, getAlt() returns an empty string.

const { src } = getPreviewUtils(content);
const { getAlt } = damAssets(content);

// Will render alt="" if no AltText exists in the asset
<img src={src(content.decorativeIcon)} alt={getAlt(content.decorativeIcon)} />;
📘

Note

Avoid omitting fallback text unless the image is purely decorative. Empty alt text signals assistive technologies to ignore the image.

💡

Tip

Don't skip the fallback parameter. Empty alt text marks images as decorative, which isn't always what you want.

Working with Multiple Asset Types

Content references in your CMS can accept different types of media like images, videos, or files. Without type checking, you'd need to manually check the __typename property and cast types yourself:

// Without type utilities (verbose and error-prone)
if (content.media?.item?.__typename === "cmp_PublicImageAsset") {
  const renditions = (content.media.item as PublicImageAsset).Renditions;
}

The SDK provides type checking utilities through damAssets() that handle this automatically with proper TypeScript type narrowing.

Available Type Checkers

  • isDamImageAsset() - Checks for image assets (cmp_PublicImageAsset) Unlocks access to: Renditions, AltText, Width, Height, FocalPoint

  • isDamVideoAsset() - Checks for video assets (cmp_PublicVideoAsset) Unlocks access to: Renditions, AltText

  • isDamRawFileAsset() - Checks for file assets (cmp_PublicRawFileAsset) Unlocks access to: Url, Title, Description, MimeType

  • getDamAssetType() - Returns the asset type as a string: 'image' | 'video' | 'file' | 'unknown' Useful for switch-case logic or displaying asset type information

  • isDamAsset() - Validates that a content reference is any type of DAM asset Returns true if the reference contains a valid image, video, or file asset

Type-Safe Conditional Rendering

Use type guards when you need different rendering logic for each asset type. TypeScript automatically narrows the type inside each conditional block, giving you full autocomplete and type safety:

import { damAssets } from '@optimizely/cms-sdk';

export default function MediaComponent({ content }) {
  const {
    isDamImageAsset,
    isDamVideoAsset,
    isDamRawFileAsset,
    getSrcset,
    getAlt,
  } = damAssets(content);

  if (isDamImageAsset(content.media)) {
    // TypeScript knows content.media.item is PublicImageAsset
    return (
      <img
        src={content.media.item.Url}
        srcSet={getSrcset(content.media)}
        alt={getAlt(content.media, 'Media asset')}
      />
    );
  }

  if (isDamVideoAsset(content.media)) {
    // TypeScript knows content.media.item is PublicVideoAsset
    return (
      <video src={content.media.item.Url} controls>
        {content.media.item.AltText && (
          <track kind="captions" label={content.media.item.AltText} />
        )}
      </video>
    );
  }

  if (isDamRawFileAsset(content.media)) {
    // TypeScript knows content.media.item is PublicRawFileAsset
    return (
      <a href={content.media.item.Url} download>
        {content.media.item.Title || 'Download File'}
      </a>
    );
  }

  return null;
}

Switch-Case Pattern with getDamAssetType()

For more declarative code or when you need the asset type as a value, use getDamAssetType(). This works well when the asset type needs to be passed to other functions or displayed to users:

import { damAssets } from '@optimizely/cms-sdk';

export default function AssetRenderer({ content }) {
  const { getSrcset, getAlt, getDamAssetType } = damAssets(content);
  const assetType = getDamAssetType(content.media);

  switch (assetType) {
    case 'image':
      return (
        <img
          src={content.media.item.Url}
          srcSet={getSrcset(content.media)}
          alt={getAlt(content.media, 'Image')}
        />
      );
    case 'video':
      return <video src={content.media.item.Url} controls />;
    case 'file':
      return (
        <a href={content.media.item.Url} download>
          {content.media.item.Title || 'Download'}
        </a>
      );
    default:
      return <p>No media available</p>;
  }
}

Validating Asset Existence

Use isDamAsset() when you don't care about the specific asset type but need to verify that a valid DAM asset exists. This is useful for optional fields or when providing fallback content:

import { damAssets } from '@optimizely/cms-sdk';

export default function OptionalMedia({ content }) {
  const { isDamAsset, getDamAssetType } = damAssets(content);

  if (!isDamAsset(content.media)) {
    return <div>No media uploaded</div>;
  }

  const assetType = getDamAssetType(content.media);
  return <div>Valid {assetType} asset detected</div>;
}
📘

Note

Type guards check the asset's __typename property. They return false for null, undefined, or content references without a valid asset item.

Use DAM assets with Next.js image optimization

When using Next.js, configure your DAM hostname in remotePatterns. Without this configuration, Next.js does not optimize DAM-hosted images.

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "*.cms.optimizely.com",
      },
      {
        protocol: "https",
        hostname: "*.cmstest.optimizely.com",
      },
      {
        protocol: "https",
        hostname: "your-dam-instance.optimizely.com", // Replace with your hostname
      },
    ],
  },
};

export default nextConfig;

Then use the Next.js Image component normally.

import Image from 'next/image';
import { damAssets } from '@optimizely/cms-sdk';

export default function OptimizedImage({ content }) {
  const { src } = getPreviewUtils(content);
  const { getSrcset, getAlt } = damAssets(content);

  return (
    <Image
      src={src(content.image)}
      alt={getAlt(content.image, 'Default alt text')}
      width={800}
      height={600}
      srcSet={getSrcset(content.image)}
      sizes="(max-width: 768px) 100vw, 50vw"
    />
  );
}

Complete example

import { damAssets } from '@optimizely/cms-sdk';
import Image from 'next/image';

type Props = {
  content: ContentProps<typeof ArticleContentType>;
};

export default function ArticleHero({ content }: Props) {
  const { src } = getPreviewUtils(content);
  const { getSrcset, getAlt } = damAssets(content);

  return (
    <article>
      <header>
        <h1>{content.title}</h1>

        {/* Primary hero image with responsive srcset */}
        <Image
          src={src(content.heroImage)}
          alt={getAlt(content.heroImage, 'Article hero image')}
          width={1200}
          height={600}
          srcSet={getSrcset(content.heroImage)}
          sizes="100vw"
          priority
        />
      </header>

      <div>
        {/* Thumbnail image */}
        <img
          src={src(content.thumbnail)}
          srcSet={getSrcset(content.thumbnail)}
          sizes="(max-width: 768px) 100px, 200px"
          alt={getAlt(content.thumbnail)}
        />

        <div>{content.summary}</div>
      </div>
    </article>
  );
}