CORS Error on Messenger Widget Init in Next.js App Router

Hey everyone, running into a wall with the Web Messaging SDK in a Next.js 14 project using the App Router. The goal is to embed the messenger widget into a custom React component that loads dynamically based on user role. It works fine in a static HTML file, but inside the Next.js environment, I get a CORS error every time the script tries to initialize.

Here is the setup. I’m using a custom hook to load the script tag dynamically because Next.js handles scripts differently in the new router. The hook looks like this:

import { useEffect } from 'react';

export function useGenesysMessenger() {
 useEffect(() => {
 const script = document.createElement('script');
 script.src = 'https://webmessaging.genesyscloud.com/messenger.js';
 script.async = true;
 script.onload = () => {
 console.log('Script loaded');
 // Attempt to init
 if (window.GenesysWebMessaging) {
 window.GenesysWebMessaging.init({
 organizationId: 'my-org-id',
 deploymentId: 'my-deployment-id'
 });
 }
 };
 document.body.appendChild(script);
 return () => document.body.removeChild(script);
 }, []);
}

The script loads without issue, but window.GenesysWebMessaging.init throws a CORS policy error in the browser console. The error message says:

Access to script at 'https://webmessaging.genesyscloud.com/messenger.js' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Wait, that doesn’t make sense. The script itself loaded. The error happens when the internal SDK code tries to fetch configuration or connect to the WebSocket endpoint. I checked the network tab. The initial GET for messenger.js returns 200. But then a subsequent POST to https://api.mypurecloud.com/api/v2/webmessaging/... fails with 403 Forbidden and the CORS error.

I’ve tried adding next.config.js rewrites and headers to allow genesyscloud.com domains, but that didn’t help. Is there a specific configuration object I need to pass to init to handle the origin correctly in a server-side rendered environment? Or is the SDK expecting a specific header that Next.js is stripping out during the hydration phase?

Any pointers on how to debug this? I’m stuck.

CORS usually isn’t the real problem here. Next.js App Router runs server-side by default, and you can’t initialize a browser-only SDK on the server. The error happens because the script tries to load in an environment where window doesn’t exist.

You need to wrap that initialization in a useEffect or check for typeof window !== 'undefined'. The docs for the Web Messaging SDK say: “The SDK must be initialized on the client side.”

Here is how I handle it in a C# backend serving React, but the principle is the same. Don’t let the server touch the DOM logic.

'use client';

import { useEffect, useRef } from 'react';

export default function MessengerWidget() {
 const containerRef = useRef<HTMLDivElement>(null);

 useEffect(() => {
 // Only run in browser
 if (typeof window !== 'undefined') {
 const script = document.createElement('script');
 script.src = 'https://webmessaging.genesys.cloud/sdk/js/genesyscloud-webmessaging-sdk.min.js';
 script.async = true;
 
 script.onload = () => {
 // @ts-ignore - SDK types aren't always perfect
 const gc = window.GenesysCloudWebMessagingSdk;
 gc.init({
 deploymentId: 'your-deployment-id',
 region: 'mypurecloud.com'
 });
 };

 document.body.appendChild(script);

 return () => {
 document.body.removeChild(script);
 };
 }
 }, []);

 return <div ref={containerRef} id="genesys-web-messaging-container" />;
}

If you’re still seeing CORS, check if you’re proxying the request through Next.js API routes incorrectly. The widget talks directly to Genesys, not your server.