Botón Flotante de Chat - Código para tu Web

Integración Simple

Añade un botón de chat flotante o un chatbox completo a tu sitio web con solo copiar y pegar el código

🚀

Fácil Integración

Solo copia y pega el código en tu sitio web

🔄

Personaliza la URL

Reemplaza la URL por la tuya usando el indicativo de tu país

🔑

URL Única

Obtén tu URL personalizada registrándote en perfilu.com

📝 Información Importante sobre la URL

Para personalizar correctamente el botón de chat, debes modificar la URL en el código HTML:

https://perfilu.com/asistenteperfilu/573126304535
1
Adquiere la url Para ello debe registrarse en perfilu.com. Con los datos dados en la plataforma ya el chat queda habilitado.
2
Reemplaza el código de país: El número "57" corresponde al indicativo de Colombia. Debes cambiarlo por el indicativo de tu país (ej: 34 para España, 52 para México, etc.)
3
Mantén el resto de la estructura: Conserva la parte "perfilu.com/asistenteperfilu/" y solo modifica el número según tu país y necesidades.

Ejemplos para diferentes países:

España: https://perfilu.com/asistenteperfilu/34612345678
México: https://perfilu.com/asistenteperfilu/521234567890
Argentina: https://perfilu.com/asistenteperfilu/5491123456789

Nota: Las clases CSS están nombradas con el sufijo -perfilu para evitar conflictos con otros estilos que ya puedas tener en tu sitio web.

1

Paso 1: Copiar el CSS

Copia el siguiente bloque de código y pégalo dentro de la etiqueta <head> de tu página HTML.

<style>
    /* Estilos para el contenedor principal del botón */
    .chatbot-perfilu {
        position: fixed;
        bottom: 25px;
        right: 25px;
        z-index: 9999;
        text-decoration: none;
    }

    /* Estilos para el círculo del botón */
    .boton-icono-perfilu {
        width: 60px;
        height: 60px;
        background-color: #007bff;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        transition: all 0.3s ease;
        animation: pulse-perfilu 2s infinite;
    }

    /* Efecto al pasar el mouse sobre el botón */
    .chatbot-perfilu:hover .boton-icono-perfilu {
        transform: scale(1.1);
        background-color: #0056b3;
        box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
    }

    /* Estilos para el icono SVG */
    .boton-icono-perfilu svg {
        width: 32px;
        height: 32px;
        fill: white;
    }

    /* Definición de la animación de pulso */
    @keyframes pulse-perfilu {
        0% {
            box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7);
        }
        70% {
            box-shadow: 0 0 0 15px rgba(0, 123, 255, 0);
        }
        100% {
            box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
        }
    }
</style>
2

Paso 2: Copiar el HTML

Copia el siguiente bloque de código y pégalo dentro de la etiqueta <body> de tu página HTML, idealmente justo antes de la etiqueta de cierre </body>.

Recuerda: Modifica la URL reemplazando el indicativo de país (57) por el de tu país.

<!-- Botón Flotante del Chatbot -->
<a href="https://perfilu.com/asistenteperfilu/573126304535" target="_blank" class="chatbot-perfilu">
    <div class="boton-icono-perfilu">
        <!-- Icono de Robot (SVG) -->
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white">
            <path d="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V17A1,1 0 0,1 22,18H21V19A5,5 0 0,1 16,24H8A5,5 0 0,1 3,19V18H2A1,1 0 0,1 1,17V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
        </svg>
    </div>
</a>
<!-- Fin del Botón Flotante -->

Nota: El chatbox básico incluye un modal completo con interfaz de chat. Copia todo el código CSS y HTML para implementarlo.

1

Paso 1: Copiar el CSS

Copia el siguiente bloque de código y pégalo dentro de la etiqueta <head> de tu página HTML.

<style>
    /* --- ESTILOS DEL BOTÓN FLOTANTE --- */
    .floating-button-perfilu {
        position: fixed;
        bottom: 25px;
        left: 25px;
        width: 60px;
        height: 60px;
        background-color: #007bff;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        cursor: pointer;
        z-index: 10000;
        transition: all 0.3s ease;
        animation: pulse-perfilu 2s infinite;
    }

    .floating-button-perfilu:hover {
        transform: scale(1.1);
        background-color: #0056b3;
    }

    .floating-button-perfilu svg {
        width: 32px;
        height: 32px;
        fill: white;
    }

    @keyframes pulse-perfilu {
        0% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7); }
        70% { box-shadow: 0 0 0 15px rgba(0, 123, 255, 0); }
        100% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); }
    }

    /* --- ESTILOS DEL MODAL --- */
    .modal-overlay-perfilu {
        display: none;
        position: fixed;
        z-index: 9999;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        overflow: auto;
        background-color: rgba(0,0,0,0.6);
        justify-content: center;
        align-items: center;
    }

    .modal-content-perfilu {
        position: relative;
        width: 100%;
        height: 100%;
        max-width: 800px;
        max-height: 90vh;
        margin: auto;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .modal-close-perfilu {
        position: absolute;
        top: 15px;
        right: 25px;
        color: #f1f1f1;
        font-size: 40px;
        font-weight: bold;
        cursor: pointer;
        z-index: 10001;
    }

    .modal-close-perfilu:hover {
        color: #bbb;
    }

    /* --- ESTILOS DEL CHATBOX --- */
    :root {
        --perfilu-green: #128C7E;
        --perfilu-light-green: #25D366;
        --perfilu-dark-green: #075E54;
        --perfilu-gray: #ECE5DD;
        --perfilu-white: #FFFFFF;
        --perfilu-blue: #3498DB;
        --perfilu-gray-light: #F5F5F5;
        --perfilu-gray-dark: #DCF8C6;
        --perfilu-gray-message: #FFFFFF;
        --perfilu-gray-time: #A0A0A0;
        --perfilu-gray-header: #F0F0F0;
        --perfilu-gray-input: #F0F0F0;
        --perfilu-gray-border: #CCCCCC;
        --perfilu-gray-icon: #9E9E9E;
        --perfilu-gray-hover: #EEEEEE;
        --perfilu-gray-active: #E0E0E0;
        --perfilu-shadow: 0 1px 0.5px rgba(0,0,0,0.13);
    }

    .perfilu-chat-container-perfilu {
        width: 100%;
        height: 100vh;
        max-height: 100vh;
        background-color: var(--perfilu-white);
        border-radius: 0;
        box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }

    .perfilu-chatbox-perfilu {
        flex: 1;
        padding: 15px;
        overflow-y: auto;
        display: flex;
        flex-direction: column;
        gap: 10px;
        background-color: var(--perfilu-gray);
        background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+CiAgPHJlY3Qgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiBmaWxsPSIjZWNlNWRkIi8+CiAgPHBhdGggZD0iTTAgMGgyMHYyMEgweiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZGRkIiBzdHJva2Utd2lkdGg9IjEiLz4KPC9zdmc+');
    }

    .perfilu-message-perfilu {
        max-width: 75%;
        padding: 8px 12px;
        border-radius: 8px;
        position: relative;
        animation: perfilu-fadeIn-perfilu 0.3s;
        box-shadow: var(--perfilu-shadow);
        word-wrap: break-word;
    }

    @keyframes perfilu-fadeIn-perfilu {
        from { opacity: 0; transform: translateY(10px); }
        to { opacity: 1; transform: translateY(0); }
    }

    .perfilu-message-perfilu.received {
        align-self: flex-start;
        background-color: var(--perfilu-white);
        border-bottom-left-radius: 3px;
    }

    .perfilu-message-perfilu.sent {
        align-self: flex-end;
        background-color: var(--perfilu-gray-dark);
        color: #000;
        border-bottom-right-radius: 3px;
    }

    .perfilu-timestamp-perfilu {
        font-size: 11px;
        color: var(--perfilu-gray-time);
        display: block;
        margin-top: 5px;
        text-align: right;
    }

    .perfilu-message-perfilu.received .perfilu-timestamp-perfilu {
        text-align: left;
    }

    .perfilu-chat-input-perfilu {
        padding: 10px 5px;
        background-color: var(--perfilu-gray-input);
        display: flex;
        align-items: center;
        border-top: 1px solid var(--perfilu-gray-border);
        flex-shrink: 0;
    }

    .perfilu-chat-input-perfilu button {
        background: none;
        border: none;
        color: var(--perfilu-gray-icon);
        font-size: 20px;
        margin: 0 5px;
        cursor: pointer;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .perfilu-chat-input-perfilu button:hover {
        background-color: var(--perfilu-gray-hover);
    }

    .perfilu-chat-input-perfilu textarea {
        flex: 1;
        padding: 10px 15px;
        border: none;
        border-radius: 20px;
        background-color: var(--perfilu-white);
        font-size: 16px;
        outline: none;
        resize: none;
        max-height: 120px;
        min-height: 20px;
        line-height: 1.4;
    }

    .perfilu-chat-input-perfilu .perfilu-send-button-perfilu {
        background-color: var(--perfilu-light-green);
        color: var(--perfilu-white);
    }

    .perfilu-chat-input-perfilu .perfilu-send-button-perfilu:hover {
        background-color: #1ebe57;
    }

    .perfilu-chat-input-perfilu .perfilu-newline-button-perfilu {
        background-color: var(--perfilu-blue);
        color: var(--perfilu-white);
    }

    .perfilu-chat-input-perfilu .perfilu-newline-button-perfilu:hover {
        background-color: #2980b9;
    }

    .perfilu-typing-indicator-perfilu {
        display: flex;
        align-items: center;
        padding: 10px 15px;
        background-color: var(--perfilu-white);
        border-radius: 8px;
        border-bottom-left-radius: 3px;
        max-width: 70%;
        box-shadow: var(--perfilu-shadow);
    }

    .perfilu-typing-dots-perfilu {
        display: flex;
        align-items: center;
    }

    .perfilu-typing-dot-perfilu {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background-color: #777;
        margin: 0 2px;
        animation: perfilu-typingAnimation-perfilu 1.4s infinite;
    }

    .perfilu-typing-dot-perfilu:nth-child(1) { animation-delay: 0s; }
    .perfilu-typing-dot-perfilu:nth-child(2) { animation-delay: 0.2s; }
    .perfilu-typing-dot-perfilu:nth-child(3) { animation-delay: 0.4s; }

    @keyframes perfilu-typingAnimation-perfilu {
        0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }
        30% { transform: translateY(-10px); opacity: 1; }
    }

    @media (min-width: 769px) {
        .modal-content-perfilu {
            width: 90%;
            height: 90vh;
        }
        .perfilu-chat-container-perfilu {
            height: 90vh;
            max-height: 90vh;
            border-radius: 10px;
        }
        .perfilu-message-perfilu {
            max-width: 70%;
        }
    }
</style>
2

Paso 2: Copiar el HTML y JavaScript

Copia el siguiente bloque de código y pégalo dentro de la etiqueta <body> de tu página HTML.

<!-- Botón Flotante para abrir el chat -->
<div id="openModalBtn-perfilu" class="floating-button-perfilu">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white">
        <path d="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V17A1,1 0 0,1 22,18H21V19A5,5 0 0,1 16,24H8A5,5 0 0,1 3,19V18H2A1,1 0 0,1 1,17V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
    </svg>
</div>

<!-- Estructura del Modal -->
<div id="chatModal-perfilu" class="modal-overlay-perfilu">
    <div class="modal-content-perfilu">
        <span class="modal-close-perfilu">×</span>
        
        <!-- Contenedor del Chatbox -->
        <div class="perfilu-chat-container-perfilu">
            <div class="perfilu-chatbox-perfilu" id="perfilu-chatbox-perfilu">
                <div class="perfilu-message-perfilu received">
                    <p>Bienvenido. ¿En qué puedo ayudarle hoy?</p>
                    <span class="perfilu-timestamp-perfilu">10:00 AM</span>
                </div>
            </div>
            
            <div class="perfilu-chat-input-perfilu">
                <button><i class="fas fa-paperclip"></i></button>
                <textarea id="perfilu-messageInput-perfilu" placeholder="Escriba un mensaje aquí..."></textarea>
                <button class="perfilu-newline-button-perfilu" id="perfilu-newlineButton-perfilu" title="Salto de línea">
                    <i class="fas fa-level-down-alt"></i>
                </button>
                <button class="perfilu-send-button-perfilu" id="perfilu-sendButton-perfilu" title="Enviar mensaje">
                    <i class="fas fa-paper-plane"></i>
                </button>
            </div>
        </div>
    </div>
</div>

<script>
    // --- SCRIPT PARA CONTROLAR EL MODAL ---
    const modal = document.getElementById('chatModal-perfilu');
    const openBtn = document.getElementById('openModalBtn-perfilu');
    const closeBtn = document.getElementsByClassName('modal-close-perfilu')[0];

    openBtn.onclick = function() {
        modal.style.display = 'flex';
    }

    closeBtn.onclick = function() {
        modal.style.display = 'none';
    }

    window.onclick = function(event) {
        if (event.target == modal) {
            modal.style.display = 'none';
        }
    }

    // --- SCRIPT DEL CHATBOX ---
    let isNewlineMode = false;
    
    function getWaIdFromUrl() {
        return "573126304535"; // Reemplaza con tu ID
    }

    function linkify(text) {
        const urlPattern = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
        return text.replace(urlPattern, function(url) {
            let href = url;
            if (!url.match(/^[a-zA-Z]+:\/\//)) {
                href = 'http://' + url;
            }
            return '<a href="' + href + '" target="_blank" rel="noopener noreferrer">' + url + '</a>';
        });
    }

    async function sendMessage() {
        const messageInput = document.getElementById('perfilu-messageInput-perfilu');
        const messageText = messageInput.value.trim();
        
        if (messageText === '') return;
        
        const messageDiv = document.createElement('div');
        messageDiv.className = 'perfilu-message-perfilu sent';
        
        const messageParagraph = document.createElement('p');
        messageParagraph.textContent = messageText;
        
        const timestamp = document.createElement('span');
        timestamp.className = 'perfilu-timestamp-perfilu';
        timestamp.textContent = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
        
        messageDiv.appendChild(messageParagraph);
        messageDiv.appendChild(timestamp);
        
        document.getElementById('perfilu-chatbox-perfilu').appendChild(messageDiv);
        
        messageInput.value = '';
        messageInput.style.height = 'auto';
        
        const chatbox = document.getElementById('perfilu-chatbox-perfilu');
        chatbox.scrollTop = chatbox.scrollHeight;
        
        const WaId = getWaIdFromUrl();
        
        try {
            showTypingIndicator();
            
            if (!sessionStorage.getItem("id_conversa")) {
                sessionStorage.setItem("id_conversa", "conv_" + crypto.randomUUID());
            }
            
            const id_conversa = sessionStorage.getItem("id_conversa");
            
            // Reemplaza esta URL con la de tu webhook real
            const response = await fetch('https://tuasistente.perfilu.com/webhook/6c631315-ea72-4d66-9875-bdbb387e97f9', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    "token": "6c631315-ea72-4d66-9875-bdbb387e97f9",
                    "establecimiento": "General",
                    "WaId": WaId,
                    "agenda": {
                        "accion": "chat_message",
                        "nombre_profesional": "",
                        "especialidad": "",
                        "idconversa": id_conversa,
                        "fecha": "",
                        "body": messageText
                    }
                })
            });
            
            hideTypingIndicator();
            
            if (!response.ok) throw new Error(`Error en la respuesta: ${response.status}`);
            
            const data = await response.json();
            
            let respuestaFinal = "";
            if (Array.isArray(data) && data.length > 0 && data[0].output) {
                respuestaFinal = data[0].output;
            } else if (data.mensaje_limpio) {
                respuestaFinal = data.mensaje_limpio;
            } else if (data.output) {
                respuestaFinal = data.output;
            } else {
                respuestaFinal = "Recibí tu mensaje. ¿En qué más puedo ayudarte?";
            }
            
            if (respuestaFinal) {
                addAssistantMessage(respuestaFinal);
            }
            
        } catch (error) {
            console.error('Error al llamar a la API:', error);
            hideTypingIndicator();
            addAssistantMessage("Lo siento, hubo un error al procesar tu mensaje. Por favor, intenta de nuevo.");
        }
    }

    function addAssistantMessage(messageText) {
        const messageDiv = document.createElement('div');
        messageDiv.className = 'perfilu-message-perfilu received';
        
        const messageParagraph = document.createElement('p');
        let textWithLinks = linkify(messageText);
        const formattedText = textWithLinks
            .replace(/\*\*(.*?)\*\*/g, '<b>$1</b>')
            .replace(/\*(.*?)\*/g, '<i>$1</i>')
            .replace(/\n/g, '<br>');
        
        messageParagraph.innerHTML = formattedText;
        
        const timestamp = document.createElement('span');
        timestamp.className = 'perfilu-timestamp-perfilu';
        timestamp.textContent = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
        
        messageDiv.appendChild(messageParagraph);
        messageDiv.appendChild(timestamp);
        
        document.getElementById('perfilu-chatbox-perfilu').appendChild(messageDiv);
        
        const chatbox = document.getElementById('perfilu-chatbox-perfilu');
        chatbox.scrollTop = chatbox.scrollHeight;
    }

    function showTypingIndicator() {
        const typingDiv = document.createElement('div');
        typingDiv.id = 'perfilu-typing-indicator-perfilu';
        typingDiv.className = 'perfilu-typing-indicator-perfilu';
        
        const dotsContainer = document.createElement('div');
        dotsContainer.className = 'perfilu-typing-dots-perfilu';
        
        for (let i = 0; i < 3; i++) {
            const dot = document.createElement('div');
            dot.className = 'perfilu-typing-dot-perfilu';
            dotsContainer.appendChild(dot);
        }
        
        typingDiv.appendChild(dotsContainer);
        document.getElementById('perfilu-chatbox-perfilu').appendChild(typingDiv);
        
        const chatbox = document.getElementById('perfilu-chatbox-perfilu');
        chatbox.scrollTop = chatbox.scrollHeight;
    }

    function hideTypingIndicator() {
        const typingIndicator = document.getElementById('perfilu-typing-indicator-perfilu');
        if (typingIndicator) {
            typingIndicator.remove();
        }
    }

    function insertNewline() {
        const messageInput = document.getElementById('perfilu-messageInput-perfilu');
        const start = messageInput.selectionStart;
        messageInput.value = messageInput.value.substring(0, start) + '\n' + messageInput.value.substring(messageInput.selectionEnd);
        messageInput.selectionStart = messageInput.selectionEnd = start + 1;
        messageInput.style.height = 'auto';
        messageInput.style.height = (messageInput.scrollHeight) + 'px';
        messageInput.focus();
    }

    // Eventos de botones
    document.getElementById('perfilu-sendButton-perfilu').addEventListener('click', sendMessage);
    document.getElementById('perfilu-newlineButton-perfilu').addEventListener('click', insertNewline);

    document.getElementById('perfilu-messageInput-perfilu').addEventListener('keydown', function(e) {
        if (e.key === 'Enter') {
            if (isNewlineMode || e.ctrlKey || e.metaKey || e.shiftKey) {
                e.preventDefault();
                insertNewline();
            } else {
                e.preventDefault();
                sendMessage();
            }
        }
    });

    document.getElementById('perfilu-messageInput-perfilu').addEventListener('input', function() {
        this.style.height = 'auto';
        this.style.height = (this.scrollHeight) + 'px';
    });
</script>

Síguenos en @perfilucolombia unete y enterate de mi como asistente virtual