Documentation Summary

AI Support Assistant

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">
    &#x21bb; </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);
	}
};