Source code
Pendo > Resource Center > Custom Module
HTML
<!-- This module also requires a script to be directly embedded within the Site Options > UI Configuration > HTML Includes > Add to HEAD element. This is necessary because Pendo does not support JavaScript imports -->
<!-- Import n8n chat styling -->
<link href="https://cdn.jsdelivr.net/npm/@n8n/chat/dist/style.css" rel="stylesheet" />
<!-- n8n chat window is now contolled by HTML in pendo>
<div id="n8n-chat"></div>
<button id="clearChatButton" class="rmui-clear-chat-button" title="Reset Chat">
↻ </button>
<div class="rmui-kayako-container" style="display:none;">
<div class="rmui-kayako-header">
<div class="rmui-kayako-title">Need help?</div>
<p>Raise a support ticket with RightMarket and we'll email you back as soon as possible.</p>
</div>
<form action="https://rightmarket.kayako.com/api/v1/conversations.json" method="post" class="rmui-kayako-form">
<label>Name</label>
<input type="text" name="name" id="rmid-kayako-name" required>
<label>Email</label>
<input type="email" name="email" id="rmid-kayako-email" required>
<label>Subject</label>
<input type="text" name="subject" required>
<label>Message</label>
<textarea name="contents" required></textarea>
<input type="hidden" name="form_id" value="9">
<input type="hidden" name="field_values[raised_from]" id="rmid-kayako-page">
<input type="submit" value="Create support ticket">
</form>
<div class="rmui-kayako-response">
<div class="rmui-kayako-title">Thank you for raising a support request with RightMarket.</div>
<p>A member of our team will be in touch as soon as possible.</p>
<a class="rmui-kayako-raise-another-ticket" href="#">Raise another ticket</a>
</div>
</div>
CSS
/* --- Chat Container & Layout --- */
#n8n-chat {
width: 100%;
height: 100%;
}
.chat-header {
display: none;
}
.chat-layout {
padding: 0px;
max-width: 100%;
border-radius: 0px;
position: relative;
}
.chat-message-from-user {
background-color: #777980;
}
.chat-message-markdown {
font-size: 100% !important;
}
/* --- Kayako Form Styling (The "Contact Support" form) --- */
.rmui-kayako-container {
margin: 30px;
line-height: 20px;
}
.rmui-kayako-container a {
color: #1733f0;
text-decoration: underline;
}
.rmui-kayako-title {
font-weight: 500;
margin-bottom: 5px;
}
.rmui-kayako-form label {
display: block;
margin: 12px 0px 2px 0px;
}
.rmui-kayako-form input,
.rmui-kayako-form textarea {
width: 100%;
padding: 11px 12px;
border-radius: 10px;
background-color: #fafaff;
border: 1px solid #eee; /* Added subtle border */
box-sizing: border-box; /* Fixes width+padding scroll issues */
}
/* Only apply min-height to the Kayako form textarea, NOT the chat input */
.rmui-kayako-form textarea {
min-height: 125px;
}
.rmui-kayako-form input[type=submit] {
background-color: #1733f0;
color: #fff;
border-radius: 25px;
padding: 15px 22px;
margin-top: 20px;
border: none;
cursor: pointer;
}
.rmui-kayako-form input[type=submit]:hover {
transition: all 0.2s ease;
transform: translateY(-3px);
}
.rmui-kayako-response {
display: none;
}
/* --- Reset Button Styling (The circular arrow) --- */
.rmui-clear-chat-button {
position: absolute !important;
/* Adjust these if it moves too far */
bottom: 14px;
right: 55px;
z-index: 2147483647 !important;
width: 24px;
height: 24px;
padding: 0;
border-radius: 50%;
background-color: transparent !important;
color: #999 !important;
border: none !important;
font-size: 25px;
line-height: 24px;
text-align: center;
cursor: pointer;
transition: color 0.2s ease, transform 0.2s ease;
}
.rmui-clear-chat-button:hover {
color: #3A32FF !important;
background-color: #f5f5f5 !important;
}
.rmui-spin {
animation: spin 1s linear infinite;
color: #3A32FF !important;
pointer-events: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* --- RESOLUTION CARD STYLES (The "Did this resolve..." box) --- */
.rmui-kayako-resolution {
background-color: #F4F6F8 !important; /* Light Gray Card Background */
padding: 20px !important;
border-radius: 8px !important;
text-align: center !important;
margin: 15px 10px !important;
border: 1px solid #E1E4E8 !important;
display: none; /* Hidden by default */
animation: slideUp 0.3s ease-out;
box-shadow: 0 2px 8px rgba(0,0,0,0.05); /* Subtle shadow for depth */
}
/* This class is added by JS to show the box */
.rmui-kayako-resolution.show {
display: block !important;
}
.rmui-kayako-title {
font-size: 15px !important;
font-weight: 600 !important;
color: #1A2B42 !important; /* Dark text */
margin-bottom: 15px !important;
display: block !important;
font-family: inherit !important;
}
.rmui-kayako-buttons {
display: flex !important;
justify-content: center !important;
gap: 15px !important; /* Space between buttons */
}
/* --- THE BUTTONS (Yes / No) --- */
.rmui-kayako-button {
background-color: #98A2B3 !important; /* Default Slate Gray */
color: white !important;
border: none !important;
padding: 10px 30px !important; /* Size of the button */
border-radius: 6px !important; /* Slightly rounded corners */
font-size: 14px !important;
font-weight: 600 !important;
cursor: pointer !important;
transition: all 0.2s ease-in-out !important;
min-width: 70px !important;
text-align: center !important;
box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
}
/* --- HOVER EFFECT --- */
.rmui-kayako-button:hover {
background-color: #3A32FF !important; /* Vibrant Blue */
transform: translateY(-2px) !important; /* Slight lift */
box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important; /* Drop shadow */
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
JavaScript
(function() { // --- ISOLATION WRAPPER ---
// 1. CONFIGURATION
var CONFIG = {
webhookUrl: "https://rightmarket-platform.app.n8n.cloud/webhook/df817ac5-0cb9-4d01-bc88-8f6dcc74ec0a/chat",
sessionKey: 'sessionId',
ticketKey: 'n8nTicketRaised',
chatId: 'n8n-chat',
btnId: 'clearChatButton',
sendBtnClass: '.chat-input-send-button'
};
// 2. INITIAL VISIBILITY
if (typeof $ !== 'undefined') {
$('#' + CONFIG.chatId).show();
$('#' + CONFIG.btnId).show();
}
// 3. HELPER FUNCTIONS
var toStr = function(v) { return (v == null ? '' : String(v)); };
var nonEmptyOrAnon = function(v) { return (toStr(v).trim() || 'Anonymous'); };
function getChatMetadata() {
var pf = (typeof Pageflex_Menu_Specification === 'object' && Pageflex_Menu_Specification) || {};
var first = toStr(pf.firstName).trim();
var last = toStr(pf.lastName).trim();
var fullNameRaw = [first, last].filter(Boolean).join(' ').trim();
var pageRaw = (window.location && window.location.href) || '';
var emailRaw = pf.logonName || pf.email || '';
return {
fullName: nonEmptyOrAnon(fullNameRaw),
page: nonEmptyOrAnon(pageRaw),
email: nonEmptyOrAnon(emailRaw),
rawName: fullNameRaw,
rawEmail: emailRaw
};
}
// 4. PERSISTENCE CHECK
if (!localStorage.getItem(CONFIG.sessionKey)) {
var initialId = 'sess-' + Math.random().toString(36).substring(7) + '-' + Date.now();
localStorage.setItem(CONFIG.sessionKey, initialId);
}
// 5. RESET FUNCTION
var performReset = function(event) {
if(event) event.preventDefault();
var clearButton = document.getElementById(CONFIG.btnId);
var container = document.getElementById(CONFIG.chatId);
if (clearButton) {
clearButton.classList.add("rmui-spin");
clearButton.disabled = true;
}
var newSessionId = 'reset-' + Math.random().toString(36).substring(7) + '-' + Date.now();
window.N8N_FORCED_SESSION_ID = newSessionId;
localStorage.setItem(CONFIG.sessionKey, newSessionId);
localStorage.removeItem(CONFIG.ticketKey);
if(container) container.innerHTML = '';
if (typeof window.loadAIChat === 'function') {
window.loadAIChat(CONFIG.webhookUrl);
}
setTimeout(function() {
if (clearButton) {
clearButton.classList.remove("rmui-spin");
clearButton.disabled = false;
}
}, 1000);
};
// 6. VISUAL STYLER
setInterval(function() {
var container = document.getElementById(CONFIG.chatId);
if (!container) return;
var root = null;
if (container.shadowRoot && container.shadowRoot.querySelector(CONFIG.sendBtnClass)) {
root = container.shadowRoot;
} else {
var nested = container.querySelector('div');
if (nested && nested.shadowRoot && nested.shadowRoot.querySelector(CONFIG.sendBtnClass)) {
root = nested.shadowRoot;
}
}
if (!root) return;
if (!root.querySelector('#rmui-fix-styles')) {
var style = document.createElement('style');
style.id = 'rmui-fix-styles';
style.textContent = `
/* --- 1. CHAT INPUT BAR --- */
form, .chat-input-container {
position: relative !important;
background-color: #ffffff !important;
border-color: #ffffff !important;
}
textarea {
background-color: #ffffff !important;
word-break: break-word !important;
padding-right: 70px !important;
box-sizing: border-box !important;
overflow-x: hidden !important;
}
/* --- 2. RESET BUTTON (SAFE ABSOLUTE) --- */
#${CONFIG.btnId}, .rmui-clear-chat-button {
position: absolute !important;
right: 45px !important;
bottom: 50% !important;
transform: translateY(50%) !important;
top: auto !important; left: auto !important;
width: 24px !important; height: 24px !important;
padding: 0 !important; margin: 0 !important;
border: none !important; background: transparent !important;
color: #999 !important; cursor: pointer !important;
z-index: 100 !important;
display: flex !important; align-items: center !important; justify-content: center !important;
}
#${CONFIG.btnId}:hover { color: #3A32FF !important; }
/* --- 3. RESOLUTION CARD (Gray Box) --- */
.rmui-kayako-resolution {
background-color: #F4F6F8 !important;
padding: 16px 20px !important;
border-radius: 8px !important;
text-align: center !important;
margin: 15px 10px !important;
border: 1px solid #E1E4E8 !important;
display: none;
animation: slideUp 0.3s ease-out;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}
.rmui-kayako-resolution.show {
display: block !important;
}
.rmui-kayako-title {
font-size: 15px !important;
font-weight: 600 !important;
color: #1A2B42 !important;
margin-bottom: 12px !important;
display: block !important;
font-family: inherit !important;
}
.rmui-kayako-buttons {
display: flex !important;
justify-content: center !important;
gap: 12px !important;
}
/* --- 4. YES/NO BUTTONS --- */
.rmui-kayako-button {
background-color: #98A2B3 !important;
color: white !important;
border: none !important;
padding: 8px 24px !important;
border-radius: 6px !important;
font-size: 14px !important;
font-weight: 600 !important;
cursor: pointer !important;
transition: all 0.2s ease-in-out !important;
min-width: 60px !important;
text-align: center !important;
}
.rmui-kayako-button:hover {
background-color: #3A32FF !important;
transform: translateY(-2px) !important;
box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
}
@keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
`;
root.appendChild(style);
}
// --- LAYOUT FIXER: Moves Reset Button into Input Bar ---
var clearBtn = document.getElementById(CONFIG.btnId);
if (!clearBtn) clearBtn = root.getElementById(CONFIG.btnId);
var sendBtn = root.querySelector(CONFIG.sendBtnClass) || root.querySelector('button[type="submit"]');
if (clearBtn && sendBtn) {
var parent = sendBtn.parentNode;
if (clearBtn.parentNode !== parent) {
parent.insertBefore(clearBtn, sendBtn.nextSibling);
}
}
}, 1000);
// 7. FETCH OVERRIDE
(function () {
var origFetch = window.fetch;
window.fetch = async function (input, init) {
var url = typeof input === 'string' ? input : (input && input.url) || '';
var isChat = typeof CONFIG.webhookUrl === 'string' && url.indexOf(CONFIG.webhookUrl) === 0;
var method = ((init && init.method) || (input && input.method) || 'GET').toUpperCase();
if (isChat && method === 'POST') {
try {
var headers = new Headers((init && init.headers) || (input && input.headers) || {});
var isJSON = (headers.get('Content-Type') || '').toLowerCase().includes('application/json');
if (isJSON) {
var bodyText = init && init.body;
if (!bodyText && input instanceof Request) bodyText = await input.clone().text();
var data = {};
try { data = JSON.parse(bodyText || '{}'); } catch (_) { data = {}; }
if (window.N8N_FORCED_SESSION_ID) data.sessionId = window.N8N_FORCED_SESSION_ID;
else {
var currentId = localStorage.getItem(CONFIG.sessionKey);
if (currentId) data.sessionId = currentId;
}
var meta = getChatMetadata();
var hasRaisedTicket = localStorage.getItem(CONFIG.ticketKey) || 'No';
data.metadata = Object.assign({}, data.metadata || {}, {
page: meta.page,
email: meta.email,
fullName: meta.fullName,
supportTicketRaised: hasRaisedTicket
});
if (data.chatInput === 'Yes') data.metadata.feedback = 'feedback_yes';
if (data.chatInput === 'No') data.metadata.feedback = 'feedback_no';
var newInit = Object.assign({}, init, { headers: headers, body: JSON.stringify(data) });
var fetchPromise = origFetch.call(this, input, newInit);
fetchPromise.then(function(response) {
if (response.ok) {
setTimeout(function() {
if (window.showResolutionFeedback) window.showResolutionFeedback();
}, 1500);
}
});
return fetchPromise;
}
} catch (e) { console.warn('[n8n] inject error', e); }
}
return origFetch.apply(this, arguments);
};
})();
// 8. INITIAL LOAD
if (typeof window.loadAIChat === 'function') {
window.loadAIChat(CONFIG.webhookUrl);
}
setTimeout(function() {
var clearButton = document.getElementById(CONFIG.btnId);
if (clearButton) {
var newButton = clearButton.cloneNode(true);
clearButton.parentNode.replaceChild(newButton, clearButton);
newButton.addEventListener('click', performReset);
newButton.onclick = performReset;
}
}, 500);
// 9. FEEDBACK UI LOGIC (WITH DOM BLOCKING)
// Helper to get text from the visible chat
function getLastBotMessageText(root) {
if (!root) return '';
// Select all potential message containers
var messageNodes = root.querySelectorAll('[class*="message"], [class*="chat-bubble"], [class*="n8n-chat__message"]');
if (!messageNodes.length) return '';
// Get the very last one
var lastNode = messageNodes[messageNodes.length - 1];
// Try to find the text content
return (lastNode.innerText || lastNode.textContent || '').trim().toLowerCase();
}
// Helper to count messages (to avoid showing on first hello)
function getMessageCount(root) {
if (!root) return 0;
return root.querySelectorAll('[class*="message"], [class*="chat-bubble"]').length;
}
window.showResolutionFeedback = function() {
var container = document.getElementById(CONFIG.chatId);
var root = container ? (container.shadowRoot || container) : null;
if (!root) return;
// --- CHECK 1: MESSAGE COUNT ---
// If there are fewer than 2 messages (e.g. just "Hello"), do NOT show feedback
if (getMessageCount(root) < 2) {
console.log("Feedback skipped: Not enough messages.");
return;
}
// --- CHECK 2: TEXT BLOCKLIST ---
// Get the last visible message text
var lastText = getLastBotMessageText(root);
var blockedPhrases = [
"hi there",
"glad i could help",
"provide more details"
];
for (var i = 0; i < blockedPhrases.length; i++) {
if (lastText.includes(blockedPhrases[i])) {
console.log("Feedback blocked by phrase: " + blockedPhrases[i]);
return; // STOP HERE
}
}
var chatMessagesContainer = root.querySelector('.n8n-chat__messages') || root.querySelector('[class*="messages"]');
if (!chatMessagesContainer) return;
if (root.querySelector('.rmui-kayako-resolution')) return;
// Render Card
var card = document.createElement('div');
card.className = 'rmui-kayako-resolution show';
var title = document.createElement('span');
title.className = 'rmui-kayako-title';
title.innerText = "Did this resolve your issue?";
card.appendChild(title);
var btnWrapper = document.createElement('div');
btnWrapper.className = 'rmui-kayako-buttons';
var yesBtn = document.createElement('div');
yesBtn.className = 'rmui-kayako-button';
yesBtn.innerText = 'Yes';
yesBtn.onclick = function() { window.handleResolution('yes'); };
var noBtn = document.createElement('div');
noBtn.className = 'rmui-kayako-button';
noBtn.innerText = 'No';
noBtn.onclick = function() { window.handleResolution('no'); };
btnWrapper.appendChild(yesBtn);
btnWrapper.appendChild(noBtn);
card.appendChild(btnWrapper);
chatMessagesContainer.appendChild(card);
setTimeout(() => { chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight; }, 100);
};
window.handleResolution = function(status) {
var textToSend = (status === 'yes' ? 'Yes' : 'No');
var container = document.getElementById(CONFIG.chatId);
if (!container) return;
var root = container.shadowRoot || container;
var card = root.querySelector('.rmui-kayako-resolution');
if (card) card.remove();
var input = root.querySelector('textarea') || root.querySelector('input');
var sendBtn = root.querySelector(CONFIG.sendBtnClass);
if (input && sendBtn) {
var nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set ||
Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
if (nativeSetter) { nativeSetter.call(input, textToSend); } else { input.value = textToSend; }
input.dispatchEvent(new Event('input', { bubbles: true }));
setTimeout(function() { sendBtn.click(); }, 50);
}
};
window.hideResolutionFeedback = function() {
var container = document.getElementById(CONFIG.chatId);
var root = container ? (container.shadowRoot || container) : null;
if (!root) return;
var card = root.querySelector('.rmui-kayako-resolution');
if (card) card.remove();
};
setInterval(function(){
var container = document.getElementById(CONFIG.chatId);
var root = container ? (container.shadowRoot || container) : null;
if(root) {
var input = root.querySelector('textarea') || root.querySelector('input');
if(input && !input.hasAttachedHide) {
input.hasAttachedHide = true;
input.addEventListener('input', window.hideResolutionFeedback);
}
}
}, 2000);
// 10. LINKS & HANDLERS (Ticket, Feedback, Suggestion, Getting Started)
// --- CONFIGURATION: MAP LINKS TO ACTIONS ---
var ACTION_MAP = {
// TYPE 1: SHOW A HIDDEN HTML CONTAINER (Your existing Support Form)
'#raise-ticket-link': {
type: 'container',
target: '.rmui-kayako-container',
webhookAction: 'ticketRaised'
},
// TYPE 2: LAUNCH PENDO GUIDE (Feedback)
'#feedback-link': {
type: 'pendoGuide',
target: 'nlfuBdt1b_nNOPHK7ijaDpb5RyA',
webhookAction: 'feedbackOpened'
},
// TYPE 3: LAUNCH PENDO GUIDE (Suggest Template)
'#suggest-template-link': {
type: 'pendoGuide',
target: 'Of7rE8z9LzQWAryhT1eqNOunW1E',
webhookAction: 'suggestionOpened'
},
// TYPE 4: LAUNCH PENDO GUIDE (Getting Started)
'#getting-started-link': {
type: 'pendoGuide',
target: 'Q0H9YlJ7AVDaPjiM2BOLoBeCLac', // <--- Your Getting Started Guide ID
webhookAction: 'gettingStartedOpened'
},
// TYPE 5: LAUNCH PENDO GUIDE (Account Settings)
'#account-settings-link': {
type: 'pendoGuide',
target: '-4MntAcoAs4LlQpYZuY7JqFJ5Uc',
webhookAction: 'accountsettingsOpened'
}
};
// Existing Kayako Form Submission Logic
if (typeof $ !== 'undefined') {
$('.rmui-kayako-form').off('submit').submit(function(e){
e.preventDefault();
$.ajax({
url: 'https://rightmarket.kayako.com/api/v1/conversations.json',
type: 'post',
data: $('.rmui-kayako-form').serialize(),
success: function(){
$(".rmui-kayako-form, .rmui-kayako-header, .rmui-kayako-response").toggle();
$(".rmui-kayako-form input, .rmui-kayako-form textarea").val("");
}
});
});
$(".rmui-kayako-raise-another-ticket").off('click').click(function() {
$(".rmui-kayako-form, .rmui-kayako-header, .rmui-kayako-response").toggle();
});
}
// --- CENTRAL LINK HANDLER ---
function handleGlobalLinkClick(event) {
var link = event.target.closest('a');
if (!link) return;
var href = link.getAttribute('href');
if (ACTION_MAP.hasOwnProperty(href)) {
event.preventDefault();
var config = ACTION_MAP[href];
var currentId = localStorage.getItem(CONFIG.sessionKey);
var meta = getChatMetadata();
// 1. Send Event to Webhook
if (currentId) {
var metaUpdate = Object.assign({}, meta);
if (href === '#raise-ticket-link') {
localStorage.setItem(CONFIG.ticketKey, 'Yes');
metaUpdate.supportTicketRaised = 'Yes';
}
fetch(CONFIG.webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: currentId,
action: config.webhookAction,
metadata: metaUpdate
})
});
}
// 2. EXECUTE ACTION
// OPTION A: Launch a Pendo Guide
if (config.type === 'pendoGuide') {
// Close the chat window first
$('#' + CONFIG.chatId).hide();
$('#' + CONFIG.btnId).hide();
// Launch the new guide
if (window.pendo) {
pendo.showGuideById(config.target);
} else {
console.warn("Pendo is not loaded");
}
}
// OPTION B: Show a Hidden Container (Legacy)
else if (config.type === 'container' && typeof $ !== 'undefined') {
var targetForm = $(config.target);
// Generic pre-fill
targetForm.find('input[name*="name"], .name-field').val(meta.rawName || '');
targetForm.find('input[name*="email"], .email-field').val(meta.rawEmail || '');
targetForm.find('input[name*="page"], .page-field').val(meta.page || '');
// Legacy Kayako pre-fill
if (href === '#raise-ticket-link') {
var nameInput = document.getElementById('rmid-kayako-name');
if (nameInput) nameInput.value = meta.rawName || '';
var emailInput = document.getElementById('rmid-kayako-email');
if (emailInput) emailInput.value = meta.rawEmail || '';
var pageInput = document.getElementById('rmid-kayako-page');
if (pageInput) pageInput.value = meta.page;
}
// Hide Chat -> Show Container
$('#' + CONFIG.chatId).hide();
$('#' + CONFIG.btnId).hide();
// Hide ALL mapped containers first
Object.values(ACTION_MAP).forEach(function(c) {
if(c.type === 'container') $(c.target).hide();
});
$(config.target).show();
}
}
}
if (window.n8nGlobalClickHandler) document.removeEventListener('click', window.n8nGlobalClickHandler);
window.n8nGlobalClickHandler = handleGlobalLinkClick;
document.addEventListener('click', handleGlobalLinkClick);
// Initial Field Population
if(typeof Pageflex_Menu_Specification !== 'undefined') {
if(Pageflex_Menu_Specification.firstName || Pageflex_Menu_Specification.lastName) {
var nameField = document.getElementById("rmid-kayako-name");
if (nameField) nameField.value = Pageflex_Menu_Specification.firstName + " " + Pageflex_Menu_Specification.lastName;
}
}
if (typeof window !== 'undefined' && window.location) {
var pageField = document.getElementById("rmid-kayako-page");
if (pageField) pageField.value = window.location.host + window.location.pathname + window.location.search;
}
})(); // --- END ISOLATION WRAPPER ---
Pageflex Storefront Site Options
HTML
<script src="https://assets.rightmarket.com/product/n8n-support-bot/script.js"></script>
assets.rightmarket.com
https://assets.rightmarket.com/product/n8n-support-bot/script.js
JavaScript
let chatInstance = null;
window.loadAIChat = async () => {
try {
const chatContainer = document.querySelector('#n8n-chat');
// Re-create only if chatInstance doesn't exist OR the container is empty
const shouldRecreate =
!chatInstance ||
!chatContainer ||
chatContainer.children.length === 0;
if (shouldRecreate) {
// Ensure container exists before injecting chat again
if (!chatContainer) {
console.warn("#n8n-chat container is missing from the DOM. Cannot load chat.");
return;
}
// Optionally clear the container (in case it's broken HTML)
chatContainer.innerHTML = '';
const { createChat } = await import('https://cdn.jsdelivr.net/npm/@n8n/chat/dist/chat.bundle.es.js');
chatInstance = await createChat({
webhookUrl: 'https://rightmarket.app.n8n.cloud/webhook/e07751cb-4572-4036-835c-8d94ba831761/chat',
webhookConfig: {
method: 'POST',
headers: {}
},
target: '#n8n-chat',
mode: 'fullscreen',
chatInputKey: 'chatInput',
chatSessionKey: 'sessionId',
metadata: {},
showWelcomeScreen: false,
defaultLanguage: 'en',
initialMessages: [
'Hi there! ?Y‘‹ How can we help you today?'
],
i18n: {
en: {
title: '',
subtitle: '',
getStarted: 'New Conversation',
inputPlaceholder: 'Type your message..',
},
},
});
}
// Show the chat window
if (chatInstance?.openWindow) {
chatInstance.openWindow();
}
}
catch (error) {
console.error("Failed to load or initialize n8n chat:", error);
}
};