Añade un botón de chat flotante o un chatbox completo a tu sitio web con solo copiar y pegar el código
Solo copia y pega el código en tu sitio web
Reemplaza la URL por la tuya usando el indicativo de tu país
Obtén tu URL personalizada registrándote en perfilu.com
Para personalizar correctamente el botón de chat, debes modificar la URL en el código HTML:
Ejemplos para diferentes países:
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.
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>
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.
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>
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>