AI Voice Widget (BETA) (Call You/Call Me)

 

Install Guide:

  1. Lines to change

    Line 327: Number in pretty format (678) 931-7883

    Line 330: Number in raw format: +16789317883

    Line 416: GHL Inbound Webhook

    Line 523: Number without country code - 6789317883

 

Copy Code:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>AI Call Interface</title>

    <style>

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

        }

        

        body {

            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

            margin: 0;

        }

        

        .call-container {

            max-width: 500px;

            margin: 0 auto;

            background: white;

            border-radius: 24px;

            overflow: hidden;

            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);

            border: 1px solid rgba(0, 0, 0, 0.05);

            position: relative;

        }

        

        .phone-header {

            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

            padding: 30px 30px 40px;

            text-align: center;

            position: relative;

            overflow: hidden;

        }

        

        .phone-header::before {

            content: '';

            position: absolute;

            top: 0;

            left: 0;

            right: 0;

            bottom: 0;

            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="white" opacity="0.1"/></pattern></defs><rect x="0" y="0" width="100" height="100" fill="url(%23circles)"/></svg>');

        }

        

        .ai-avatar {

            width: 80px;

            height: 80px;

            border-radius: 50%;

            background: rgba(255, 255, 255, 0.2);

            display: flex;

            align-items: center;

            justify-content: center;

            font-size: 2.5rem;

            margin: 0 auto 20px;

            border: 3px solid rgba(255, 255, 255, 0.3);

            position: relative;

            z-index: 1;

            transition: all 0.3s ease;

        }

        

        .ai-avatar.talking {

            animation: pulse 1.5s infinite;

            box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);

        }

        

        @keyframes pulse {

            0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); }

            70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(255, 255, 255, 0); }

            100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }

        }

        

        .header-title {

            color: white;

            font-size: 1.3rem;

            font-weight: 600;

            margin-bottom: 8px;

            position: relative;

            z-index: 1;

        }

        

        .header-subtitle {

            color: rgba(255, 255, 255, 0.8);

            font-size: 0.9rem;

            position: relative;

            z-index: 1;

        }

        

        .mode-selector {

            display: flex;

            background: #f1f5f9;

            margin: 30px;

            border-radius: 16px;

            padding: 6px;

            position: relative;

        }

        

        .mode-option {

            flex: 1;

            padding: 12px 20px;

            text-align: center;

            border-radius: 12px;

            font-weight: 500;

            cursor: pointer;

            transition: all 0.3s ease;

            position: relative;

            z-index: 2;

        }

        

        .mode-option.active {

            background: white;

            color: #667eea;

            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

        }

        

        .call-interface {

            padding: 0 30px 30px;

        }

        

        .call-section {

            display: none;

            animation: slideIn 0.3s ease-out;

        }

        

        .call-section.active {

            display: block;

        }

        

        @keyframes slideIn {

            from { opacity: 0; transform: translateY(20px); }

            to { opacity: 1; transform: translateY(0); }

        }

        

        .phone-display {

            background: #f8fafc;

            border-radius: 16px;

            padding: 30px;

            text-align: center;

            margin-bottom: 30px;

            border: 2px solid #e2e8f0;

        }

        

        .phone-number {

            font-size: 2rem;

            font-weight: 700;

            color: #1e293b;

            margin-bottom: 10px;

            letter-spacing: 2px;

        }

        

        .phone-subtitle {

            color: #64748b;

            font-size: 0.9rem;

        }

        

        .call-button {

            width: 100%;

            background: linear-gradient(135deg, #10b981, #059669);

            color: white;

            border: none;

            padding: 18px;

            border-radius: 16px;

            font-size: 1.1rem;

            font-weight: 600;

            cursor: pointer;

            transition: all 0.3s ease;

            display: flex;

            align-items: center;

            justify-content: center;

            gap: 12px;

            position: relative;

            overflow: hidden;

            text-decoration: none;

        }

        

        .call-button::before {

            content: '';

            position: absolute;

            top: 0;

            left: -100%;

            width: 100%;

            height: 100%;

            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);

            transition: left 0.5s ease;

        }

        

        .call-button:hover::before {

            left: 100%;

        }

        

        .call-button:hover {

            transform: translateY(-2px);

            box-shadow: 0 10px 25px rgba(16, 185, 129, 0.3);

        }

 

        

        .input-group {

            margin-bottom: 20px;

        }

        

        .input-label {

            display: block;

            color: #374151;

            font-weight: 500;

            margin-bottom: 8px;

            font-size: 0.9rem;

        }

        

        .phone-input {

            width: 100%;

            padding: 16px 20px;

            border: 2px solid #e5e7eb;

            border-radius: 12px;

            font-size: 1.1rem;

            transition: all 0.3s ease;

            background: white;

        }

        

        .phone-input:focus {

            outline: none;

            border-color: #667eea;

            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);

        }

        

        .callback-button {

            width: 100%;

            background: linear-gradient(135deg, #667eea, #764ba2);

            color: white;

            border: none;

            padding: 18px;

            border-radius: 16px;

            font-size: 1.1rem;

            font-weight: 600;

            cursor: pointer;

            transition: all 0.3s ease;

            display: flex;

            align-items: center;

            justify-content: center;

            gap: 12px;

            position: relative;

            overflow: hidden;

        }

        

        .callback-button:hover {

            transform: translateY(-2px);

            box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);

        }

        

        .callback-button.requesting {

            background: linear-gradient(135deg, #f59e0b, #d97706);

            animation: pulse 1s infinite;

        }

        

        .status-message {

            text-align: center;

            padding: 20px;

            background: #f0fdf4;

            border-radius: 12px;

            margin-top: 20px;

            border: 1px solid #bbf7d0;

            color: #15803d;

            font-weight: 500;

            display: none;

        }

        

        .status-message.show {

            display: block;

            animation: fadeIn 0.3s ease;

        }

        

        @keyframes fadeIn {

            from { opacity: 0; }

            to { opacity: 1; }

        }

        

        .call-icon {

            font-size: 1.2rem;

        }

        

        /* Responsive */

        @media (max-width: 480px) {

            .call-container {

                margin: 0 10px;

            }

            

            .phone-header {

                padding: 25px 20px 35px;

            }

            

            .call-interface {

                padding: 0 20px 20px;

            }

            

            .mode-selector {

                margin: 20px;

            }

            

            .phone-number {

                font-size: 1.6rem;

            }

        }

    </style>

</head>

<body>

    <div class="call-container">

        <div class="phone-header">

            <div class="ai-avatar" id="aiAvatar">πŸ€–</div>

            <h2 class="header-title">Talk to Our AI Agent</h2>

            <p class="header-subtitle">Available 24/7 • Average response time: < 2 seconds</p>

        </div>

        

        <div class="mode-selector">

            <div class="mode-option active" onclick="switchMode('inbound')">

                πŸ“ž Call AI

            </div>

            <div class="mode-option" onclick="switchMode('outbound')">

                πŸ“² AI Calls You

            </div>

        </div>

        

        <div class="call-interface">

            <!-- Inbound Call Section -->

            <div class="call-section active" id="inbound">

                <div class="phone-display">

                    <div class="phone-number">(678) 931-7883</div>

                    <p class="phone-subtitle">Tap to copy • Click call to connect instantly</p>

                </div>

                <a href="tel:+16789317883" class="call-button" id="callButton">

                    <span class="call-icon">πŸ“ž</span>

                    <span id="callText">Call Now - Free Demo</span>

                </a>

            </div>

            

            <!-- Outbound Call Section -->

            <div class="call-section" id="outbound">

                <div class="input-group">

                    <label class="input-label">Your Phone Number</label>

                    <input type="tel" class="phone-input" id="phoneInput" placeholder="(555) 123-4567" />

                </div>

                <button class="callback-button" id="callbackButton" onclick="requestCallback()">

                    <span class="call-icon">πŸ“²</span>

                    <span id="callbackText">Have AI Call Me in 30 Seconds</span>

                </button>

            </div>

            

            <div class="status-message" id="statusMessage"></div>

        </div>

    </div>

 

    <script>

        let currentMode = 'inbound';

        

        function switchMode(mode) {

            currentMode = mode;

            

            // Update active mode selector

            document.querySelectorAll('.mode-option').forEach(option => {

                option.classList.remove('active');

            });

            event.target.classList.add('active');

            

            // Show/hide sections

            document.querySelectorAll('.call-section').forEach(section => {

                section.classList.remove('active');

            });

            document.getElementById(mode).classList.add('active');

            

            // Update header

            const avatar = document.getElementById('aiAvatar');

            const title = document.querySelector('.header-title');

            const subtitle = document.querySelector('.header-subtitle');

            

            if (mode === 'inbound') {

                title.textContent = 'Talk to Our AI Agent';

                subtitle.textContent = 'Available 24/7 • Average response time: < 2 seconds';

                avatar.textContent = 'πŸ€–';

            } else {

                title.textContent = 'AI Will Call You';

                subtitle.textContent = 'Enter your number • AI calls in 30 seconds';

                avatar.textContent = 'πŸ“ž';

            }

            

            // Hide status message

            document.getElementById('statusMessage').classList.remove('show');

        }

 

        

        function requestCallback() {

            const phoneInput = document.getElementById('phoneInput');

            const button = document.getElementById('callbackButton');

            const avatar = document.getElementById('aiAvatar');

            const text = document.getElementById('callbackText');

            

            // Check if phone number has at least 10 digits

            const digitsOnly = phoneInput.value.replace(/\D/g, '');

            if (digitsOnly.length < 10) {

                phoneInput.style.borderColor = '#ef4444';

                phoneInput.focus();

                showStatus('⚠️ Please enter a valid 10-digit phone number');

                return;

            }

            

            // Reset border color

            phoneInput.style.borderColor = '#e5e7eb';

            

            // Start requesting state

            button.classList.add('requesting');

            avatar.classList.add('talking');

            text.textContent = 'Setting up call...';

            

            console.log('Attempting to call webhook with number:', digitsOnly);

            

            // Make the webhook call

            fetch('https://services.leadconnecto…c94', {

                method: 'POST',

                headers: {

                    'Content-Type': 'application/json',

                },

                body: JSON.stringify({

                    to: digitsOnly

                })

            })

            .then(response => {

                console.log('Webhook response:', response);

                text.textContent = 'Call scheduled successfully!';

                showStatus(`πŸš€ Perfect! Our AI will call ${phoneInput.value} shortly. Please keep your phone nearby and answer when it rings!`);

            })

            .catch(error => {

                console.error('Webhook error:', error);

                // Even if there's a CORS error, the webhook might still work

                text.textContent = 'Call scheduled!';

                showStatus(`πŸ“ž Great! Our AI will call ${phoneInput.value} shortly. Please keep your phone nearby!`);

            })

            .finally(() => {

                setTimeout(() => {

                    // Reset after 5 seconds

                    button.classList.remove('requesting');

                    avatar.classList.remove('talking');

                    text.textContent = 'Have AI Call Me in 30 Seconds';

                    phoneInput.value = '';

                }, 5000);

            });

        }

        

        function showStatus(message) {

            const statusDiv = document.getElementById('statusMessage');

            statusDiv.textContent = message;

            statusDiv.classList.add('show');

            

            setTimeout(() => {

                statusDiv.classList.remove('show');

            }, 8000);

        }

        

        // Phone number formatting - improved version

        document.getElementById('phoneInput').addEventListener('input', function(e) {

            let input = e.target;

            let value = input.value.replace(/\D/g, ''); // Remove all non-digits

            let cursorPosition = input.selectionStart;

            let oldLength = input.value.length;

            

            // Format the number

            let formattedValue = '';

            if (value.length > 0) {

                if (value.length <= 3) {

                    formattedValue = `(${value}`;

                } else if (value.length <= 6) {

                    formattedValue = `(${value.slice(0, 3)}) ${value.slice(3)}`;

                } else {

                    formattedValue = `(${value.slice(0, 3)}) ${value.slice(3, 6)}-${value.slice(6, 10)}`;

                }

            }

            

            // Update the input value

            input.value = formattedValue;

            

            // Adjust cursor position if needed

            let newLength = input.value.length;

            if (newLength > oldLength) {

                cursorPosition += (newLength - oldLength);

            }

            

            // Set cursor position

            input.setSelectionRange(cursorPosition, cursorPosition);

        });

        

        // Handle backspace properly

        document.getElementById('phoneInput').addEventListener('keydown', function(e) {

            if (e.key === 'Backspace') {

                let input = e.target;

                let value = input.value;

                let cursorPos = input.selectionStart;

                

                // If cursor is right after a formatting character, move it back

                if (cursorPos > 0 && (value[cursorPos - 1] === ')' || value[cursorPos - 1] === ' ' || value[cursorPos - 1] === '-')) {

                    e.preventDefault();

                    input.setSelectionRange(cursorPos - 1, cursorPos - 1);

                }

            }

        });

        

        // Show validation on blur

        document.getElementById('phoneInput').addEventListener('blur', function(e) {

            const digitsOnly = e.target.value.replace(/\D/g, '');

            if (digitsOnly.length === 10) {

                e.target.style.borderColor = '#10b981';

            } else if (digitsOnly.length > 0 && digitsOnly.length < 10) {

                e.target.style.borderColor = '#ef4444';

            } else {

                e.target.style.borderColor = '#e5e7eb';

            }

        });

        

        // Reset border on focus

        document.getElementById('phoneInput').addEventListener('focus', function(e) {

            e.target.style.borderColor = '#667eea';

        });

        

        // Copy phone number on click

        document.querySelector('.phone-number').addEventListener('click', function() {

            navigator.clipboard.writeText('6789317883').then(function() {

                showStatus('πŸ“‹ Phone number copied to clipboard!');

            });

        });

    </script>

</body>

</html>

 


Inputs & Options:

 

  • data-color: The hex code of your choice that is responsible for the color of the widget.

  • data-assistant-id: Your assistant’s ID

  • data-account-id: Your GoHighLevel Location ID where the assistant is from

  • data-position: The position on the screen.

    • Choices (all lowercase)

      • bottom-right

      • bottom-left

      • top-right

      • top-left

 

  • data-theme: Dark or light theme.

    • Choices (all lowercase):

      • light

      • dark

  • data-show-prompt: true or false to show the message above the widget button on idle

    • Choices (all lowercase):

      • true

      • false

 

  • data-prompt-message: The message in the prompt popup (if visible)

 

  • data-assistant-name: The name displayed on the widget for the assistant

 

  • data-button-icon: The icon of the idle widget button to open the actual conversation window

    • Choices (all lowercase)

      • chat (default): Speech bubble icon

      • message: Message box icon

      • question: Question mark icon

      • headset: Support headset icon

 

  • data-greeting-message: The first message in the chat widget from the assistant (the pre-determined message that shows when the user opens the widget)

 

  • data-prompts: Allows you to add prompts to the widget to get the user to click on pre-determined questions (that could be fine-tuned in your knowledge base) to start the conversation

Was this article helpful?