Skip to main content

Outline

At a glance
  • Context detection: The frontend identifies the CMS Edit view via the preview_token URL parameter.
  • Draft fetching: Use the SDK's getPreviewContent method to bypass public caches and retrieve unpublished versions.
  • Live updates: The communicationinjector.js script enables real-time refreshes by listening for the optimizely:cms:contentSaved event.
  • Cache bypass: Requesting specific version GUIDs ensures editors see "hot" content directly from the index.

In a decoupled Optimizely CMS 13 architecture, the frontend application is responsible for detecting when it is being viewed in an "Edit" context and adjusting its data fetching logic accordingly. This involves extracting security tokens, communicating with the CMS via specialized scripts, and ensuring that the data displayed is the most recent draft, bypassing any public-facing caches.

Detecting the Preview Context

When an editor opens a page in the CMS Edit view, the CMS loads the frontend application inside an iframe. The URL sent to this iframe contains a preview_token query parameter. Your application must check for this parameter at the routing or top-level component level to determine if it should switch to "Preview Mode."

Implementing the Graph Client for Preview

The Optimizely Graph JavaScript SDK provides built-in support for fetching draft content. Instead of a standard query that uses a public HMAC key, you should use the getPreviewContent method. This method specifically handles the resolution of draft versions based on the parameters (such as content key and version) passed from the CMS.

Code Example: Initializing and Fetching Preview Data

import { GraphClient } from '@optimizely/graph-client'; // Initialize the client const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY, { graphUrl: process.env.OPTIMIZELY_GRAPH_GATEWAY, }); // Extract params from the URL (provided by the CMS Preview Routing) const searchParams = new URL(window.location.href).searchParams; const previewParams = { key: searchParams.get('key'), ver: searchParams.get('ver'), loc: searchParams.get('loc'), token: searchParams.get('preview_token') }; // Fetch the draft version const response = await client.getPreviewContent(previewParams);

The Role of communicationinjector.js

To facilitate a live editing experience, the frontend must include a bridge script hosted by the CMS: communicationinjector.js. This script sets up a message-passing channel between the CMS UI and your application, even across different domains.

Inclusion in React/Next.js

// In your Preview Layout or Page component <script src=&lcub;`$&lcub;process.env.OPTIMIZELY_CMS_URL&rcub;/util/javascript/communicationinjector.js`&rcub;></script>

Listening for Live Updates (Content Saved Events)

A critical part of the developer's job in CMS 13 is ensuring that the preview refreshes when an editor saves a change. Because the frontend doesn't "know" when a save happens in the backend, it must listen for the optimizely:cms:contentSaved event emitted by the injector script.

When this event fires, it provides an updated previewToken. Your application should re-trigger its GraphQL queries using this new token to reflect the latest changes immediately.

useEffect(() => &lcub; const handleContentSaved = (event) => &lcub; const &lcub; previewToken, previewUrl &rcub; = event.detail; // Re-fetch data and update local state refreshData(previewToken); &rcub;; window.addEventListener('optimizely:cms:contentSaved', handleContentSaved); return () => window.removeEventListener('optimizely:cms:contentSaved', handleContentSaved); &rcub;, []);

Cache-Bypass Behaviors

One of the most common issues in headless previews is seeing stale data due to caching. Optimizely Graph handles this by design:

  • Unpublished Versioning: When you request a specific version (using the {version} token and a preview_token), Optimizely Graph automatically bypasses the standard query cache.
  • Real-time Delivery: Since the preview request targets a specific draft GUID, the system ensures you are getting the "hot" version of the content directly from the index, ensuring that the editor's "Preview" is truly live.

Conclusion

Successfully handling preview requests requires a proactive approach from the frontend developer. By correctly implementing token extraction, utilizing the getPreviewContent helper, and subscribing to CMS save events, you can provide editors with a high-fidelity, interactive environment that feels as integrated as traditional in-process CMS architectures.