Custom Button that Controls Front Chat Widget

Click the button below to open Front Chat. The chat frame will auto-hide either when the user clicks the button again, or when they close it from within the widget itself. This behavior is made possible using a MutationObserver to detect when the chat iframe changes or closes.

⚠️ This setup uses a custom approach to control the Front Chat widget and hide it completely from view. Since it depends on how the widget/chat iframe currently works behind the scenes, future updates from Front could break this implementation.
🚧 Please note: Because this is not officially supported by Front, results may vary. Front Support cannot provide direct assistance with any issue you may encounter.
💡 This demo was built using Tailwind CSS and JavaScript.

JavaScript used:


let chatFrontLoaded = false; // Tracks if Front Chat has loaded
let chatVisible = false;     // Tracks if the chat is currently open

// Waits until the FrontChat SDK is avaliable
function waitForFrontChat(callback) {
  const interval = setInterval(() => {
    if (window.FrontChat) {
      clearInterval(interval);
      callback(); // Run init once FrontChat is ready
    }
  }, 100);
}

// Initializes the Front Chat widget with custom settings
function initFrontChat() {
  window.FrontChat('init', {
    chatId: 'YOUR_CHAT_ID_HERE', // Replace with your real Chat ID
    useDefaultLauncher: true, 
    shouldHideExpandButton: true, 
    onInitCompleted: () => {
      chatFrontLoaded = true;
      window.FrontChat('hide');      // Start the widget hidden
      shrinkChatIframe();            // Shrink iframe to 1px
      setupMutationObserver();       // Watch for manual closes

      // Enable the custom "Chat with us" button now that it's safe
      const chatBtn = document.querySelector('.spider-front-chat-btn');
      if (chatBtn) {
        chatBtn.disabled = false;
        chatBtn.classList.remove('opacity-50', 'cursor-not-allowed');
      }
    }
  });
}

// Shrinks the Front chat iframe so it's effectively invisible
function shrinkChatIframe() {
  const iframe = document.querySelector('#front-chat-iframe');
  if (iframe) {
    iframe.style.width = '1px';
    iframe.style.height = '1px';
  }
}

// Expands the iframe to its normal size
function expandChatIframe() {
  const iframe = document.querySelector('#front-chat-iframe');
  if (iframe) {
    iframe.style.width = '';
    iframe.style.height = '';
  }
}

// Makes the custom button toggle the chat open/closed
function setupCustomChatButton() {
  const chatBtn = document.querySelector('.spider-front-chat-btn');
  if (!chatBtn) return;

  chatBtn.addEventListener('click', (e) => {
    e.preventDefault();
    if (!chatFrontLoaded) return;

    const iframe = document.querySelector('#front-chat-iframe');
    if (!iframe) return;

    if (chatVisible) {
      // User wants to close chat via button
      window.FrontChat('hide');
      shrinkChatIframe();
      chatVisible = false;
      chatBtn.textContent = 'Chat with us';
    } else {
      // User wants to open chat via button
      expandChatIframe();
      window.FrontChat('show');
      chatVisible = true;
      chatBtn.textContent = 'Close Chat';
    }
  });
}

// Watches the iframe for style changes to detect chat closing
function setupMutationObserver() {
  const iframe = document.querySelector('#front-chat-iframe');
  if (!iframe) return;

  const observer = new MutationObserver(() => {
    const isChatVisible = iframe.offsetWidth > 100 && iframe.offsetHeight > 100;
    if (!isChatVisible) {
      // User closed chat via widget UI
      shrinkChatIframe();

      const chatBtn = document.querySelector('.spider-front-chat-btn');
      if (chatBtn) {
        chatBtn.textContent = 'Chat with us';
      }

      // Keep internal state in sync
      chatVisible = false;
    }
  });

  observer.observe(iframe, {
    attributes: true,
    attributeFilter: ['style', 'class'] // Watch for style changes
  });
}

// Start the whole process once the DOM is ready
document.addEventListener('DOMContentLoaded', () => {
  waitForFrontChat(() => {
    initFrontChat();
    setupCustomChatButton();
  });
});