Amazon Connect Chat Widget Programmatic Launch: Complete JavaScript Guide

Contents

1. What Is Amazon Connect Chat Widget Programmatic Launch?

Amazon Connect chat widget programmatic launch – By default, Amazon Connect’s hosted communications widget renders a floating chat icon in the corner of your webpage. When a visitor clicks it, the chat opens. Simple — but not always what you need.

Programmatic launch is the capability to control the widget’s open/close behavior entirely from your own JavaScript code, bypassing or augmenting the default icon. This unlocks scenarios like:

🎯 Custom Trigger Elements

Open chat from any element — a “Chat With Us” button in your nav, a help icon in your app, or a CTA mid-page.

⚡ Lazy Asset Loading

Don’t load widget scripts until a user actually clicks — shaving hundreds of milliseconds off your initial page load.

🔗 URL Auto-Launch

Drop a shareable link in an email or ad that opens the chat widget the moment the page loads.

🪟 New Window Launch

Pop chat open in a floating browser window — perfect for single-page apps or kiosk environments.

📌 Session Persistence

Keep the customer in the same chat session even if they open a new tab or navigate between subdomains.

🔌 Programmatic Disconnect

End the chat session in code — on tab close, page hide, or context switch — instead of waiting for the user to click End Chat.

All of this is controlled through a single Amazon Connect API: amazon_connect('customLaunchBehavior', { ... }), combined with the ChatJS library for advanced custom interfaces. This guide covers every angle, with complete, copy-paste-ready code.

2. Prerequisites & Widget Setup

Before writing any JavaScript, you need a working Amazon Connect widget. Here is what you need in place:

1. An Amazon Connect Instance

Log into your AWS Console, navigate to Amazon Connect, and ensure your instance is active and configured to receive chat contacts.

2. A Contact Flow for Chat

Create or use an existing contact flow that handles inbound chat contacts. The “Sample inbound flow” is a good starting point for testing.

3. A Communications Widget Created in the Admin Console

In Amazon Connect → Channels → Communication Widgets, create and customize your widget. At the end of this wizard, Amazon Connect generates your embed snippet containing your unique snippetId.

4. Your Domain Allow-Listed

Add your website domain in Step 3 of the widget wizard so the hosted widget can render on your pages. For local dev, add http://localhost:PORT.

Once those are in place, Amazon Connect gives you a standard embed snippet that looks like this:

// Paste this in your <head> or before </body>
<script type="text/javascript">
  (function(w, d, x, id) {
    s = d.createElement('script');
    s.src = 'https://your-instance.my.connect.aws/connectwidget/static/amazon-connect-chat-interface-client.js';
    s.async = 1;
    s.id = id;
    d.getElementsByTagName('head')[0].appendChild(s);
    w[x] = w[x] || function() {
      (w[x].ac = w[x].ac || []).push(arguments);
    };
  })(window, document, 'amazon_connect', 'YOUR-WIDGET-ID');

  amazon_connect('snippetId', 'YOUR-SNIPPET-ID');
  amazon_connect('styles', {
    iconType: 'CHAT',
    openChat:  { color: '#ffffff', backgroundColor: '#0073bb' },
    closeChat: { color: '#ffffff', backgroundColor: '#0073bb' }
  });
</script>

Everything from this point forward is layered on top of this snippet by calling additional amazon_connect() functions.

3. The customLaunchBehavior API Reference

The customLaunchBehavior configuration key is the central control panel for programmatic launch. It accepts an object with the following fields:

OptionTypeDefaultDescription
skipIconButtonAndAutoLaunchbooleanundefinedWhen true, the widget auto-launches on page load without the user clicking the floating icon. Useful for URL-triggered auto-launch scenarios.
alwaysHideWidgetButtonbooleanundefinedWhen true, the default Amazon Connect floating icon is never rendered (unless there’s an ongoing chat session). Use this when you want full control via a custom trigger element.
programmaticLaunchfunctionundefinedA function that receives a launchCallback. You bind this callback to any DOM event (button click, scroll, timer) to open the widget at exactly the right moment.

ℹ️ All fields are optional

You can use any combination of these three fields. They are designed to compose — for example, hide the default button and bind a custom trigger, while also supporting auto-launch from a URL parameter.

4. Use Case 1: Launch Widget from Any Custom Button

This is the most common real-world need: you have a “Chat With Us” CTA button in your nav or hero section, and you want clicking it to open the Amazon Connect chat — without the default floating icon getting in the way.

The HTML

<!-- Place this anywhere on your page -->
<button id="launch-widget-btn" class="chat-cta">
  💬 Chat With Us
</button>

The Widget Script

<script type="text/javascript">
  (function(w, d, x, id) {
    s = d.createElement('script');
    s.src = 'https://YOUR-INSTANCE.my.connect.aws/connectwidget/static/amazon-connect-chat-interface-client.js';
    s.async = 1;
    s.id = id;
    d.getElementsByTagName('head')[0].appendChild(s);
    w[x] = w[x] || function() {
      (w[x].ac = w[x].ac || []).push(arguments);
    };
  })(window, document, 'amazon_connect', 'YOUR-WIDGET-ID');

  amazon_connect('snippetId', 'YOUR-SNIPPET-ID');
  amazon_connect('styles', {
    openChat:  { color: '#ffffff', backgroundColor: '#0073bb' },
    closeChat: { color: '#ffffff', backgroundColor: '#0073bb' }
  });

  // ✅ Custom launch behavior — hides default icon, uses our button
  amazon_connect('customLaunchBehavior', {
    skipIconButtonAndAutoLaunch: true,  // don't auto-open on page load
    alwaysHideWidgetButton: true,         // hide the default floating icon
    programmaticLaunch: (function(launchCallback) {
      var btn = document.getElementById('launch-widget-btn');
      if (btn) {
        btn.addEventListener('click', launchCallback);
        // ✅ Clean up listener on page unload to prevent memory leaks
        window.onunload = function() {
          btn.removeEventListener('click', launchCallback);
        };
      }
    })
  });
</script>

Important: Remove the event listener on unload

Always clean up the event listener by calling removeEventListener inside window.onunload. Failing to do this can cause memory leaks in long-lived single-page applications.

With this setup, your custom button becomes the sole way to open the chat. The default floating icon never appears. You retain full styling control over the trigger element through your own CSS.

Also Check – Fixing Amazon Connect “acceptContact API Request Failed: Network Failure” — Complete Troubleshooting Guide

5. Use Case 2: Lazy-Load Widget Assets on Button Click

Most visitors to your contact page will never open the chat. Loading Amazon Connect’s JavaScript bundle on every page visit adds unnecessary CDN requests, parse time, and memory overhead — especially for mobile users.

The solution is to defer loading the widget’s script entirely until the user signals intent by clicking your custom button. Amazon Connect supports this pattern by moving the widget initialization inside the click handler:

<!-- HTML: your trigger button -->
<button id="launch-widget-btn">Chat With Us</button>

<script>
  var widgetLoaded = false; // guard against double-init

  document.getElementById('launch-widget-btn')
    .addEventListener('click', function() {
      if (widgetLoaded) return; // only init once
      widgetLoaded = true;

      // ✅ Initialize and load widget assets NOW (on click)
      (function(w, d, x, id) {
        var s = d.createElement('script');
        s.src = 'https://YOUR-INSTANCE.my.connect.aws/connectwidget/static/amazon-connect-chat-interface-client.js';
        s.async = 1;
        s.id = id;
        d.getElementsByTagName('head')[0].appendChild(s);
        w[x] = w[x] || function() {
          (w[x].ac = w[x].ac || []).push(arguments);
        };
      })(window, document, 'amazon_connect', 'YOUR-WIDGET-ID');

      amazon_connect('snippetId', 'YOUR-SNIPPET-ID');
      amazon_connect('styles', {
        openChat:  { color: '#fff', backgroundColor: '#0073bb' },
        closeChat: { color: '#fff', backgroundColor: '#0073bb' }
      });

      // ✅ Auto-open immediately after script loads
      amazon_connect('customLaunchBehavior', {
        skipIconButtonAndAutoLaunch: true
      });
    });
</script>

Use a loaded guard

Without the widgetLoaded boolean guard, a fast double-click could initialize the widget twice, creating duplicate connections. Always track whether initialization has already run.

6. Use Case 3: Auto-Launch Widget from a Shareable URL

Marketing campaigns, email links, and support tickets often need a way to drop customers directly into a live chat session. Instead of sending a link to a generic contact page, you can send a URL like https://yoursite.com/contact?chat=true and have the widget open automatically on load.

<script type="text/javascript">
  (function(w, d, x, id) {
    var s = d.createElement('script');
    s.src = 'https://YOUR-INSTANCE.my.connect.aws/connectwidget/static/amazon-connect-chat-interface-client.js';
    s.async = 1;
    s.id = id;
    d.getElementsByTagName('head')[0].appendChild(s);
    w[x] = w[x] || function() {
      (w[x].ac = w[x].ac || []).push(arguments);
    };
  })(window, document, 'amazon_connect', 'YOUR-WIDGET-ID');

  amazon_connect('snippetId', 'YOUR-SNIPPET-ID');
  amazon_connect('styles', {
    openChat:  { color: '#fff', backgroundColor: '#0073bb' },
    closeChat: { color: '#fff', backgroundColor: '#0073bb' }
  });

  // ✅ Check for URL parameter and auto-launch if present
  var params = new URLSearchParams(window.location.search);
  if (params.get('chat') === 'true') {
    amazon_connect('customLaunchBehavior', {
      skipIconButtonAndAutoLaunch: true  // open immediately on page load
    });
  }
</script>

With this code, visiting https://yoursite.com/support?chat=true opens the Amazon Connect widget the moment the page finishes loading. Any URL without that parameter behaves normally, showing the default widget icon.

Use this in email campaigns and support tickets

Instead of “Visit our contact page,” write “Click here to start a live chat now” and link directly to ?chat=true. It dramatically reduces the steps between intent and connection.

7. Use Case 4: Launch Amazon Connect Chat in a New Browser Window

Some applications — particularly internal tools, kiosks, or SaaS platforms — benefit from opening chat in a separate, fixed-size browser window so it doesn’t interfere with the main application UI.

<!-- A dedicated chat page: chat-window.html -->
<!-- On that page, add the widget snippet with skipIconButtonAndAutoLaunch: true -->

<!-- On your MAIN page, trigger the popup: -->
<button id="openChatWindowButton">Launch Chat</button>

<script>
  function openChatWindow() {
    var chatUrl = 'https://yoursite.com/chat-window?chat=true';
    var width  = 380;
    var height = 600;
    var left   = (window.innerWidth  - width)  / 2;
    var top    = (window.innerHeight - height) / 2;

    window.open(
      chatUrl,
      'AmazonConnectChat',
      `width=${width},height=${height},left=${left},top=${top},resizable=yes`
    );
  }

  document.getElementById('openChatWindowButton')
    .addEventListener('click', openChatWindow);
</script>

The chat-window.html page is a minimal HTML file that contains the Amazon Connect widget snippet with skipIconButtonAndAutoLaunch: true, so the chat opens automatically the moment the popup window loads.

8. Use Case 5: Persist Chat Session Across Browser Tabs

By default, if a customer opens the chat in Tab A and then navigates to a different page or opens Tab B, a new chat session starts from scratch. For long customer journeys — like e-commerce checkout flows — this is a poor experience.

Amazon Connect provides a mechanism to persist the chat session using cookies, so the customer reconnects to their existing session in any new tab on the same domain.

Step 1: Store the session in a cookie when chat connects

// Add this alongside your other amazon_connect() calls
amazon_connect('registerCallback', {
  // When chat establishes, save the session token to a cookie
  'CONNECTION_ESTABLISHED': (eventName, { chatDetails, data }) => {
    const sessionData = sessionStorage.getItem('persistedChatSession');
    if (sessionData) {
      document.cookie =
        `activeChat=${sessionData}; SameSite=None; Secure; domain=.yoursite.com`;
    }
  },
  // When chat ends, clear the cookie
  'CHAT_ENDED': () => {
    document.cookie = 'activeChat=; SameSite=None; Secure; Max-Age=0; domain=.yoursite.com';
  }
});

Step 2: Read the cookie on new tab load and restore the session

// Run this BEFORE your widget snippet on every page
const cookie = document.cookie
  .split('; ')
  .find(c => c.startsWith('activeChat='));

if (cookie) {
  const value = cookie.split('=')[1];
  // Restore the session so the widget reconnects automatically
  sessionStorage.setItem('persistedChatSession', value);
}

// Then include your normal widget snippet below...

Cross-subdomain session sharing

To share the session across subdomains like shop.yoursite.com and support.yoursite.com, set the cookie with domain=.yoursite.com (note the leading dot). This makes the cookie readable from all subdomains.

9. Use Case 6: Programmatically Disconnect the Chat Session

In some scenarios you want to end the chat session from code — for example, when the user closes the tab, navigates away, or locks their screen. Waiting for them to click “End Chat” is not always reliable.

Amazon Connect exposes a disconnect() method on the widget’s iframe contentWindow. You can call it from the host page using this pattern:

function disconnectChat() {
  const iframe = document.getElementById('amazon-connect-chat-widget-iframe');
  if (iframe && iframe.contentWindow?.connect?.ChatSession) {
    iframe.contentWindow.connect.ChatSession.disconnect();
  }
}

Disconnect on tab/browser close (pagehide)

// pagehide fires on tab close, navigation, and browser close
// It is more reliable than beforeunload, especially on mobile
window.addEventListener('pagehide', () => {
  disconnectChat();
});

Disconnect on context switch (visibilitychange)

// Fires when user switches tabs, minimizes, or locks screen
window.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    disconnectChat();
  }
  else if (document.visibilityState === 'visible') {
    // User returned — optionally re-open the widget UI
  }
});

No guarantee of completion on browser close

pagehide and beforeunload fire when the browser is destroying the page, but there is no guarantee the disconnect() network call will fully complete before the browser cleans up resources. Use beforeunload as a fallback if pagehide proves unreliable in your environment — but be aware of known iOS issues with beforeunload.

Also Check – Amazon Connect CSP Bypass: Fix Content Security Policy Violations & Embed CCP (2026)

10. Targeting Widget Elements with CSS and JavaScript

Even when you use programmatic launch, the widget still renders a frame and button elements in the DOM that you can target directly. Amazon Connect exposes specific, stable element IDs for this purpose:

SelectorWhat It Targets
#amazon-connect-open-widget-buttonThe floating button that opens the widget (visible when chat is minimized)
#amazon-connect-close-widget-buttonThe button that closes/minimizes the widget (visible when chat is open)
#amazon-connect-widget-frameThe chat iframe container, always in DOM
#amazon-connect-widget-frame.showThe chat frame while it is open/visible
#amazon-connect-widget-frame:not(.show)The chat frame while it is minimized/hidden

CSS Example: Repositioning the Widget Frame

Custom CSS OverridesCSS

/* Move the widget to the bottom-left instead of bottom-right */
#amazon-connect-widget-frame {
  bottom: 20px !important;
  left: 20px !important;
  right: auto !important;
}

/* Make the open button larger on desktop */
#amazon-connect-open-widget-button {
  width: 64px !important;
  height: 64px !important;
}

/* Animate the frame appearing */
#amazon-connect-widget-frame.show {
  animation: slideUp 0.25s ease-out;
}
@keyframes slideUp {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

JavaScript Example: Detecting Widget State

Detect Open/Close State via DOMJavaScript

function isWidgetOpen() {
  const frame = document.querySelector('#amazon-connect-widget-frame');
  return frame && frame.classList.contains('show');
}

// Observe widget open/close with MutationObserver
const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.attributeName === 'class') {
      const isOpen = isWidgetOpen();
      console.log('Widget is now:', isOpen ? 'open' : 'closed');
      // e.g. update your custom trigger button label
    }
  });
});

const frame = document.querySelector('#amazon-connect-widget-frame');
if (frame) {
  observer.observe(frame, { attributes: true });
}

11. Deep Dive: Using ChatJS for Fully Custom Widget Interfaces

The customLaunchBehavior API controls when the hosted widget appears. But if you need complete UI control — your own chat bubble, your own message thread design, your own typing indicators — you need ChatJS: Amazon Connect’s open-source browser JavaScript library.

ChatJS (amazon-connect-chatjs) communicates directly with Amazon Connect’s WebSocket and Participant Service APIs, giving you a full programmatic interface to the chat session lifecycle.

Installation

Install ChatJSShell

# npm
npm install amazon-connect-chatjs

# yarn
yarn add amazon-connect-chatjs

# CDN (no bundler)
<script src="https://unpkg.com/amazon-connect-chatjs@latest"></script>

Creating and Connecting a Customer Chat Session

ChatJS — Full Customer Session FlowJavaScript

import 'amazon-connect-chatjs';

// 1. Configure globally (call before .create())
connect.ChatSession.setGlobalConfig({
  region: 'us-east-1',
  features: {
    messageReceipts: {
      shouldSendMessageReceipts: true,
      throttleTime: 5000
    }
  }
});

// 2. Start a contact — call YOUR backend which calls StartChatContact API
const response = await fetch('https://api.yoursite.com/start-chat', {
  method: 'POST'
});
const chatDetails = await response.json();
// chatDetails: { ContactId, ParticipantId, ParticipantToken }

// 3. Create the ChatJS session
const chatSession = connect.ChatSession.create({
  chatDetails: {
    contactId:      chatDetails.ContactId,
    participantId:  chatDetails.ParticipantId,
    participantToken: chatDetails.ParticipantToken
  },
  options: { region: 'us-east-1' },
  type: 'CUSTOMER',
  disableCSM: true
});

// 4. Connect WebSocket
await chatSession.connect();

// 5. Send a message
await chatSession.sendMessage({
  contentType: 'text/plain',
  message: 'Hello, I need help with my order.'
});

// 6. Listen for incoming messages
chatSession.onMessage(event => {
  const { data } = event;
  console.log(`[${data.ParticipantRole}]: ${data.Content}`);
  // Render message in your custom UI
});

// 7. Handle connection events
chatSession.onConnectionEstablished(() => console.log('Connected'));
chatSession.onConnectionBroken(() =>  console.log('Connection broken'));
chatSession.onEnded(() =>             console.log('Chat ended'));

// 8. End session
await chatSession.disconnectParticipant();

ℹ️ChatJS v5 — AWS SDK v3 migration (May 2025)

ChatJS v5.0.0 migrated its internal dependency from AWS SDK v2 to AWS SDK v3. If you import your own AWS SDK in the same project, import ChatJS first to avoid conflicts, as ChatJS bundles its own copy of the ConnectParticipant client.

12. Troubleshooting Common Issues

Widget not opening when custom button is clicked

Ensure the programmaticLaunch function correctly references the DOM element by ID. The element must exist in the DOM at the time the script runs. If your button is rendered after the script, wrap it in a DOMContentLoaded event:

Fix: Wait for DOM ReadyJavaScript

document.addEventListener('DOMContentLoaded', () => {
  amazon_connect('customLaunchBehavior', {
    skipIconButtonAndAutoLaunch: true,
    alwaysHideWidgetButton: true,
    programmaticLaunch: (function(launchCallback) {
      const btn = document.getElementById('launch-widget-btn');
      if (btn) btn.addEventListener('click', launchCallback);
    })
  });
});

Default icon still visible despite alwaysHideWidgetButton: true

Check that the amazon_connect('customLaunchBehavior', ...) call is placed before the widget script fully initializes. The order of amazon_connect() calls matters. Configuration calls should precede the widget’s first render cycle.

Widget loads but shows a blank iframe

This usually means your domain is not allow-listed. In the Amazon Connect admin console, navigate to your widget settings and verify that your website’s domain (including protocol and port for local dev) is listed in the “Approved Domains” section.

Session not persisting across tabs

Confirm that the cookie is being set with the correct SameSite=None; Secure attributes — these are required for cross-tab cookies in modern browsers. Also verify that the cookie value is read and written to sessionStorage before the widget initializes on the new tab.

ChatJS CSM error messages in console

Messages like ChatJS-csmService: Failed to addCountAndErrorMetric are from an internal Client Side Metrics feature. They are safe to suppress by passing disableCSM: true when creating the chat session via connect.ChatSession.create().

13. Frequently Asked Questions

What is the difference between the hosted widget and ChatJS?

The hosted widget is a pre-built, Amazon-hosted UI that you embed with a short script snippet. It handles all the connection logic and UI out of the box. ChatJS is the low-level JavaScript library that underlies the widget — you use it directly when you need to build your own custom chat interface with complete control over the visual design and session lifecycle.

Can I use customLaunchBehavior with the ChatJS library directly?

No. customLaunchBehavior and amazon_connect() are configuration APIs for the hosted widget. When using ChatJS directly, you control launch behavior entirely through your own code — you call chatSession.connect() and chatSession.disconnectParticipant() whenever your application logic dictates.

Does lazy-loading the widget break any functionality?

No. All widget functionality is available regardless of when the script loads — as long as the amazon_connect() configuration calls are made before the script initializes. The queue-based amazon_connect function stores calls and replays them once the library is ready, so order and timing are handled gracefully.

Is it possible to open the widget after a delay (e.g., 30 seconds on the page)?

Yes. Simply use setTimeout inside programmaticLaunch to call launchCallback after a delay, instead of binding it to a click event. Be cautious: time-triggered pop-ups can disrupt users who are actively reading page content.

Can I pass customer context (name, email) when programmatically launching?

Yes, via the amazon_connect('contactAttributes', { ... }) call. You can pass arbitrary key-value pairs that are available in your Amazon Connect contact flow. For the pre-chat form approach with ChatJS, you supply the display name directly in the StartChatContact API call through your backend.

What’s the focus keyword and why does this article target it?

The primary focus keyword is “amazon connect chat widget programmatic launch”. It is a high-intent, developer-specific phrase with very low competition — almost no published articles target this exact string despite it being a documented Amazon Connect capability that many developers search for when building production contact center integrations.

Sources – AWS Docs, rePost, Github

Leave a Comment