| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Data Insights Explorer</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); |
| |
| body { |
| font-family: 'Poppins', sans-serif; |
| background-color: #f5f7fa; |
| color: #2d3748; |
| } |
| |
| .data-window { |
| transition: all 0.3s ease; |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); |
| } |
| |
| .data-window:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| |
| .prompt-card { |
| transition: all 0.2s ease; |
| } |
| |
| .prompt-card:hover { |
| transform: scale(1.03); |
| } |
| |
| .gradient-bg { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| } |
| |
| .window-tabs { |
| border-bottom: 2px solid #e2e8f0; |
| } |
| |
| .window-tab { |
| transition: all 0.2s ease; |
| } |
| |
| .window-tab.active { |
| border-bottom: 3px solid #667eea; |
| color: #667eea; |
| font-weight: 500; |
| } |
| |
| .window-tab:hover:not(.active) { |
| border-bottom: 3px solid #a0aec0; |
| color: #4a5568; |
| } |
| |
| .typewriter { |
| overflow: hidden; |
| border-right: 2px solid #667eea; |
| white-space: nowrap; |
| margin: 0 auto; |
| letter-spacing: 1px; |
| animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite; |
| } |
| |
| @keyframes typing { |
| from { width: 0 } |
| to { width: 100% } |
| } |
| |
| @keyframes blink-caret { |
| from, to { border-color: transparent } |
| 50% { border-color: #667eea } |
| } |
| |
| .pulse { |
| animation: pulse 2s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { transform: scale(1); } |
| 50% { transform: scale(1.05); } |
| 100% { transform: scale(1); } |
| } |
| |
| .slide-fade-enter-active { |
| transition: all 0.3s ease-out; |
| } |
| |
| .slide-fade-leave-active { |
| transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1); |
| } |
| |
| .slide-fade-enter-from, |
| .slide-fade-leave-to { |
| transform: translateX(20px); |
| opacity: 0; |
| } |
| |
| .modal-overlay { |
| background-color: rgba(0, 0, 0, 0.5); |
| } |
| |
| .modal-container { |
| max-height: 90vh; |
| } |
| </style> |
| </head> |
| <body class="min-h-screen"> |
| <div class="flex flex-col h-screen"> |
| |
| <header class="gradient-bg text-white p-4 shadow-lg"> |
| <div class="container mx-auto flex justify-between items-center"> |
| <div class="flex items-center space-x-3"> |
| <i class="fas fa-chart-network text-3xl"></i> |
| <h1 class="text-2xl font-bold">Data Insights Explorer</h1> |
| </div> |
| <div class="flex items-center space-x-4"> |
| <div class="relative group"> |
| <button id="clientSwitcher" class="flex items-center space-x-2 bg-white/20 px-3 py-1 rounded-full hover:bg-white/30 transition"> |
| <i class="fas fa-building"></i> |
| <span id="currentClientName">Select Client</span> |
| <i class="fas fa-chevron-down text-xs"></i> |
| </button> |
| <div id="clientDropdown" class="hidden absolute right-0 mt-2 w-64 bg-white rounded-md shadow-lg z-50"> |
| <div class="p-3 border-b"> |
| <div class="flex justify-between items-center"> |
| <h3 class="font-medium text-gray-700">Clients & Properties</h3> |
| <button onclick="showAddClientModal()" class="text-indigo-600 hover:text-indigo-800 text-sm flex items-center"> |
| <i class="fas fa-plus mr-1"></i> Add |
| </button> |
| </div> |
| </div> |
| <div id="clientList" class="max-h-60 overflow-y-auto"> |
| |
| </div> |
| </div> |
| </div> |
| <div class="flex items-center space-x-2 bg-white/20 px-3 py-1 rounded-full"> |
| <i class="fas fa-user-circle"></i> |
| <span>Account</span> |
| </div> |
| <button class="bg-white text-indigo-700 px-4 py-2 rounded-full font-medium hover:bg-indigo-50 transition"> |
| <i class="fas fa-sign-out-alt mr-2"></i>Logout |
| </button> |
| </div> |
| </div> |
| </header> |
| |
| |
| <main class="flex-1 container mx-auto p-4 grid grid-cols-1 lg:grid-cols-4 gap-6"> |
| |
| <div class="lg:col-span-1 space-y-4"> |
| <div class="bg-white rounded-xl p-4 shadow-md"> |
| <h2 class="text-lg font-semibold mb-3 text-indigo-700 flex items-center"> |
| <i class="fas fa-bolt mr-2"></i> Quick Insights |
| </h2> |
| <p class="text-sm text-gray-600 mb-4">Click any prompt to get instant analysis</p> |
| |
| <div class="grid grid-cols-1 gap-3"> |
| <div class="prompt-card bg-indigo-50 p-3 rounded-lg cursor-pointer hover:bg-indigo-100" onclick="runPrompt('summary')"> |
| <div class="flex items-center"> |
| <div class="bg-indigo-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-chart-pie text-indigo-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Performance Summary</h3> |
| <p class="text-xs text-gray-600">Get an overview of key metrics</p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="prompt-card bg-green-50 p-3 rounded-lg cursor-pointer hover:bg-green-100" onclick="runPrompt('traffic')"> |
| <div class="flex items-center"> |
| <div class="bg-green-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-users text-green-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Traffic Sources</h3> |
| <p class="text-xs text-gray-600">Analyze where visitors come from</p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="prompt-card bg-yellow-50 p-3 rounded-lg cursor-pointer hover:bg-yellow-100" onclick="runPrompt('keywords')"> |
| <div class="flex items-center"> |
| <div class="bg-yellow-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-key text-yellow-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Top Keywords</h3> |
| <p class="text-xs text-gray-600">See what's driving search traffic</p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="prompt-card bg-red-50 p-3 rounded-lg cursor-pointer hover:bg-red-100" onclick="runPrompt('issues')"> |
| <div class="flex items-center"> |
| <div class="bg-red-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-exclamation-triangle text-red-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Critical Issues</h3> |
| <p class="text-xs text-gray-600">Identify urgent problems</p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="prompt-card bg-purple-50 p-3 rounded-lg cursor-pointer hover:bg-purple-100" onclick="runPrompt('comparison')"> |
| <div class="flex items-center"> |
| <div class="bg-purple-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-balance-scale text-purple-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Period Comparison</h3> |
| <p class="text-xs text-gray-600">Compare performance over time</p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="prompt-card bg-blue-50 p-3 rounded-lg cursor-pointer hover:bg-blue-100" onclick="runPrompt('recommendations')"> |
| <div class="flex items-center"> |
| <div class="bg-blue-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-lightbulb text-blue-600"></i> |
| </div> |
| <div> |
| <h3 class="font-medium">Optimization Tips</h3> |
| <p class="text-xs text-gray-600">Get actionable recommendations</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="bg-white rounded-xl p-4 shadow-md"> |
| <h2 class="text-lg font-semibold mb-3 text-indigo-700 flex items-center"> |
| <i class="fas fa-history mr-2"></i> Recent Queries |
| </h2> |
| <div class="space-y-2"> |
| <div class="text-sm p-2 hover:bg-gray-50 rounded cursor-pointer" onclick="runPrompt('traffic last week')"> |
| <div class="flex justify-between"> |
| <span>Traffic last week</span> |
| <span class="text-gray-400">2h ago</span> |
| </div> |
| </div> |
| <div class="text-sm p-2 hover:bg-gray-50 rounded cursor-pointer" onclick="runPrompt('top pages')"> |
| <div class="flex justify-between"> |
| <span>Top performing pages</span> |
| <span class="text-gray-400">1d ago</span> |
| </div> |
| </div> |
| <div class="text-sm p-2 hover:bg-gray-50 rounded cursor-pointer" onclick="runPrompt('bounce rate')"> |
| <div class="flex justify-between"> |
| <span>Bounce rate analysis</span> |
| <span class="text-gray-400">3d ago</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="lg:col-span-3 space-y-6"> |
| |
| <div id="clientInfoBar" class="bg-white rounded-xl p-4 shadow-md hidden"> |
| <div class="flex justify-between items-center"> |
| <div> |
| <h2 class="font-bold text-lg" id="activeClientTitle">Client Name</h2> |
| <p class="text-sm text-gray-600" id="activeClientProperties">Properties: 0</p> |
| </div> |
| <div class="flex space-x-3"> |
| <button onclick="showEditClientModal()" class="text-indigo-600 hover:text-indigo-800 flex items-center text-sm"> |
| <i class="fas fa-edit mr-1"></i> Edit |
| </button> |
| <button onclick="showAddPropertyModal()" class="bg-indigo-600 text-white px-3 py-1 rounded-full text-sm hover:bg-indigo-700 flex items-center"> |
| <i class="fas fa-plus mr-1"></i> Add Property |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl p-4 shadow-md"> |
| <div class="flex items-center space-x-3"> |
| <div class="flex-1 relative"> |
| <input type="text" id="queryInput" placeholder="Ask about your analytics data (e.g. 'Show traffic trends for the past month')" |
| class="w-full p-4 pr-12 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <button onclick="submitQuery()" class="absolute right-3 top-1/2 transform -translate-y-1/2 bg-indigo-600 text-white p-2 rounded-full hover:bg-indigo-700 transition"> |
| <i class="fas fa-paper-plane"></i> |
| </button> |
| </div> |
| <button onclick="voiceInput()" class="bg-indigo-100 text-indigo-700 p-3 rounded-full hover:bg-indigo-200 transition"> |
| <i class="fas fa-microphone"></i> |
| </button> |
| </div> |
| <div class="mt-2 flex flex-wrap gap-2"> |
| <span class="text-xs text-gray-500">Try:</span> |
| <span class="text-xs text-indigo-600 hover:underline cursor-pointer" onclick="runPrompt('compare mobile vs desktop conversions')">compare mobile vs desktop conversions</span> |
| <span class="text-xs text-indigo-600 hover:underline cursor-pointer" onclick="runPrompt('show top exit pages')">show top exit pages</span> |
| <span class="text-xs text-indigo-600 hover:underline cursor-pointer" onclick="runPrompt('analyze click-through rates')">analyze click-through rates</span> |
| </div> |
| </div> |
| |
| |
| <div id="windowsContainer" class="space-y-6"> |
| |
| <div class="data-window bg-white rounded-xl overflow-hidden"> |
| <div class="window-tabs flex border-b border-gray-200"> |
| <div class="window-tab active px-4 py-3 font-medium">Welcome</div> |
| </div> |
| <div class="p-6"> |
| <div class="flex items-center mb-6"> |
| <div class="bg-indigo-100 p-3 rounded-full mr-4"> |
| <i class="fas fa-robot text-indigo-600 text-2xl"></i> |
| </div> |
| <div> |
| <h2 class="text-xl font-bold text-gray-800">Hello there! 👋</h2> |
| <p class="text-gray-600">I'm your Data Insights Assistant, ready to help you explore your Google Analytics and Search Console data.</p> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div class="bg-indigo-50 p-4 rounded-lg"> |
| <h3 class="font-semibold text-indigo-700 mb-2 flex items-center"> |
| <i class="fas fa-question-circle mr-2"></i> How to use |
| </h3> |
| <ul class="text-sm space-y-2 text-gray-700"> |
| <li class="flex items-start"> |
| <i class="fas fa-check-circle text-indigo-500 mt-1 mr-2"></i> |
| <span>Click any quick insight button to get started</span> |
| </li> |
| <li class="flex items-start"> |
| <i class="fas fa-check-circle text-indigo-500 mt-1 mr-2"></i> |
| <span>Type your question in natural language</span> |
| </li> |
| <li class="flex items-start"> |
| <i class="fas fa-check-circle text-indigo-500 mt-1 mr-2"></i> |
| <span>Explore multiple data views simultaneously</span> |
| </li> |
| </ul> |
| </div> |
| |
| <div class="bg-green-50 p-4 rounded-lg"> |
| <h3 class="font-semibold text-green-700 mb-2 flex items-center"> |
| <i class="fas fa-lightbulb mr-2"></i> Try asking |
| </h3> |
| <ul class="text-sm space-y-2 text-gray-700"> |
| <li class="flex items-start"> |
| <i class="fas fa-arrow-right text-green-500 mt-1 mr-2"></i> |
| <span class="cursor-pointer hover:underline" onclick="runPrompt('show me traffic sources for last month')">"Show me traffic sources for last month"</span> |
| </li> |
| <li class="flex items-start"> |
| <i class="fas fa-arrow-right text-green-500 mt-1 mr-2"></i> |
| <span class="cursor-pointer hover:underline" onclick="runPrompt('compare mobile vs desktop performance')">"Compare mobile vs desktop performance"</span> |
| </li> |
| <li class="flex items-start"> |
| <i class="fas fa-arrow-right text-green-500 mt-1 mr-2"></i> |
| <span class="cursor-pointer hover:underline" onclick="runPrompt('what are my top performing pages')">"What are my top performing pages?"</span> |
| </li> |
| </ul> |
| </div> |
| </div> |
| |
| <div class="mt-6 bg-gradient-to-r from-indigo-50 to-blue-50 p-4 rounded-lg border border-indigo-100"> |
| <div class="flex items-center"> |
| <div class="bg-indigo-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-star text-indigo-600"></i> |
| </div> |
| <h3 class="font-semibold">Pro Tip</h3> |
| </div> |
| <p class="mt-2 text-sm text-gray-700">You can ask follow-up questions on any result by clicking the "Ask More" button that appears in each data window. This maintains context for deeper analysis.</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div id="sampleWindow" class="data-window bg-white rounded-xl overflow-hidden hidden"> |
| <div class="window-tabs flex border-b border-gray-200"> |
| <div class="window-tab active px-4 py-3 font-medium">Analysis</div> |
| <div class="window-tab px-4 py-3 font-medium">Data</div> |
| <div class="window-tab px-4 py-3 font-medium">Details</div> |
| <div class="flex-1 flex justify-end items-center pr-3"> |
| <button class="text-gray-400 hover:text-gray-600 p-1"> |
| <i class="fas fa-expand"></i> |
| </button> |
| <button class="text-gray-400 hover:text-gray-600 p-1 ml-1"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| </div> |
| <div class="p-6"> |
| <div class="flex justify-between items-start mb-4"> |
| <div> |
| <h3 class="font-semibold text-lg" id="windowTitle">Sample Analysis</h3> |
| <p class="text-sm text-gray-500" id="windowSubtitle">Generated just now</p> |
| </div> |
| <button class="bg-indigo-50 text-indigo-600 px-3 py-1 rounded-full text-sm hover:bg-indigo-100 flex items-center"> |
| <i class="fas fa-comment-dots mr-1"></i> Ask More |
| </button> |
| </div> |
| |
| <div class="window-content"> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
|
|
| |
| <div id="addClientModal" class="fixed inset-0 z-50 flex items-center justify-center hidden"> |
| <div class="modal-overlay absolute inset-0 bg-black opacity-50"></div> |
| <div class="modal-container bg-white w-11/12 md:max-w-md mx-auto rounded shadow-lg z-50 overflow-y-auto"> |
| <div class="modal-content py-4 text-left px-6"> |
| <div class="flex justify-between items-center pb-3"> |
| <p class="text-2xl font-bold">Add New Client</p> |
| <button onclick="hideModal('addClientModal')" class="modal-close cursor-pointer z-50"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="clientName"> |
| Client Name |
| </label> |
| <input type="text" id="clientName" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="clientIndustry"> |
| Industry |
| </label> |
| <input type="text" id="clientIndustry" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="clientNotes"> |
| Notes |
| </label> |
| <textarea id="clientNotes" rows="3" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"></textarea> |
| </div> |
| </div> |
| <div class="flex justify-end pt-4"> |
| <button onclick="hideModal('addClientModal')" class="px-4 py-2 text-gray-600 rounded mr-2 hover:bg-gray-100"> |
| Cancel |
| </button> |
| <button onclick="addNewClient()" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700"> |
| Save Client |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="editClientModal" class="fixed inset-0 z-50 flex items-center justify-center hidden"> |
| <div class="modal-overlay absolute inset-0 bg-black opacity-50"></div> |
| <div class="modal-container bg-white w-11/12 md:max-w-md mx-auto rounded shadow-lg z-50 overflow-y-auto"> |
| <div class="modal-content py-4 text-left px-6"> |
| <div class="flex justify-between items-center pb-3"> |
| <p class="text-2xl font-bold">Edit Client</p> |
| <button onclick="hideModal('editClientModal')" class="modal-close cursor-pointer z-50"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="editClientName"> |
| Client Name |
| </label> |
| <input type="text" id="editClientName" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="editClientIndustry"> |
| Industry |
| </label> |
| <input type="text" id="editClientIndustry" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="editClientNotes"> |
| Notes |
| </label> |
| <textarea id="editClientNotes" rows="3" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"></textarea> |
| </div> |
| </div> |
| <div class="flex justify-end pt-4"> |
| <button onclick="hideModal('editClientModal')" class="px-4 py-2 text-gray-600 rounded mr-2 hover:bg-gray-100"> |
| Cancel |
| </button> |
| <button onclick="updateClient()" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700"> |
| Save Changes |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="addPropertyModal" class="fixed inset-0 z-50 flex items-center justify-center hidden"> |
| <div class="modal-overlay absolute inset-0 bg-black opacity-50"></div> |
| <div class="modal-container bg-white w-11/12 md:max-w-md mx-auto rounded shadow-lg z-50 overflow-y-auto"> |
| <div class="modal-content py-4 text-left px-6"> |
| <div class="flex justify-between items-center pb-3"> |
| <p class="text-2xl font-bold">Add New Property</p> |
| <button onclick="hideModal('addPropertyModal')" class="modal-close cursor-pointer z-50"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="propertyName"> |
| Property Name |
| </label> |
| <input type="text" id="propertyName" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="propertyUrl"> |
| Website URL |
| </label> |
| <input type="url" id="propertyUrl" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="propertyType"> |
| Property Type |
| </label> |
| <select id="propertyType" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| <option value="website">Website</option> |
| <option value="mobile-app">Mobile App</option> |
| <option value="ecommerce">E-commerce</option> |
| <option value="blog">Blog</option> |
| <option value="saas">SaaS Platform</option> |
| </select> |
| </div> |
| <div class="grid grid-cols-2 gap-4"> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="gaPropertyId"> |
| GA Property ID |
| </label> |
| <input type="text" id="gaPropertyId" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| <div> |
| <label class="block text-gray-700 text-sm font-bold mb-2" for="gscPropertyId"> |
| GSC Property ID |
| </label> |
| <input type="text" id="gscPropertyId" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"> |
| </div> |
| </div> |
| </div> |
| <div class="flex justify-end pt-4"> |
| <button onclick="hideModal('addPropertyModal')" class="px-4 py-2 text-gray-600 rounded mr-2 hover:bg-gray-100"> |
| Cancel |
| </button> |
| <button onclick="addNewProperty()" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700"> |
| Add Property |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| // Client and property management |
| let clients = [ |
| { |
| id: 'client1', |
| name: 'Acme Corp', |
| industry: 'E-commerce', |
| notes: 'Primary client, focus on conversion optimization', |
| properties: [ |
| { |
| id: 'prop1', |
| name: 'Main Website', |
| url: 'https://acme.com', |
| type: 'ecommerce', |
| gaId: 'UA-12345678-1', |
| gscId: 'https://acme.com' |
| }, |
| { |
| id: 'prop2', |
| name: 'Blog', |
| url: 'https://blog.acme.com', |
| type: 'blog', |
| gaId: 'UA-12345678-2', |
| gscId: 'https://blog.acme.com' |
| } |
| ] |
| }, |
| { |
| id: 'client2', |
| name: 'TechStart', |
| industry: 'SaaS', |
| notes: 'Early stage startup, tracking growth metrics', |
| properties: [ |
| { |
| id: 'prop3', |
| name: 'Web App', |
| url: 'https://app.techstart.com', |
| type: 'saas', |
| gaId: 'UA-87654321-1', |
| gscId: 'https://app.techstart.com' |
| } |
| ] |
| } |
| ]; |
| |
| let currentClientId = null; |
| let currentPropertyId = null; |
| |
| // Initialize the app |
| document.addEventListener('DOMContentLoaded', function() { |
| // Set up event listeners for window tabs |
| document.querySelectorAll('.window-tab').forEach(tab => { |
| tab.addEventListener('click', function() { |
| const parentWindow = this.closest('.data-window'); |
| parentWindow.querySelectorAll('.window-tab').forEach(t => t.classList.remove('active')); |
| this.classList.add('active'); |
| }); |
| }); |
| |
| // Client switcher dropdown |
| document.getElementById('clientSwitcher').addEventListener('click', function(e) { |
| e.stopPropagation(); |
| const dropdown = document.getElementById('clientDropdown'); |
| dropdown.classList.toggle('hidden'); |
| }); |
| |
| // Close dropdown when clicking outside |
| document.addEventListener('click', function() { |
| document.getElementById('clientDropdown').classList.add('hidden'); |
| }); |
| |
| // Initialize client list |
| renderClientList(); |
| |
| // Select first client by default |
| if (clients.length > 0) { |
| selectClient(clients[0].id); |
| } |
| }); |
| |
| // Render client list in dropdown |
| function renderClientList() { |
| const clientList = document.getElementById('clientList'); |
| clientList.innerHTML = ''; |
| |
| if (clients.length === 0) { |
| clientList.innerHTML = '<div class="p-3 text-center text-gray-500">No clients added yet</div>'; |
| return; |
| } |
| |
| clients.forEach(client => { |
| const clientItem = document.createElement('div'); |
| clientItem.className = 'border-b border-gray-200 last:border-b-0'; |
| |
| clientItem.innerHTML = ` |
| <div class="p-3 hover:bg-gray-50 cursor-pointer" onclick="selectClient('${client.id}')"> |
| <div class="flex justify-between items-center"> |
| <div> |
| <h4 class="font-medium">${client.name}</h4> |
| <p class="text-xs text-gray-500">${client.industry} • ${client.properties.length} properties</p> |
| </div> |
| <i class="fas fa-chevron-right text-gray-400 text-xs"></i> |
| </div> |
| </div> |
| <div id="properties-${client.id}" class="hidden bg-gray-50 pl-4"> |
| ${client.properties.map(prop => ` |
| <div class="p-2 hover:bg-gray-100 cursor-pointer flex items-center" onclick="selectProperty('${client.id}', '${prop.id}')"> |
| <i class="fas fa-globe mr-2 text-gray-500 text-sm"></i> |
| <span>${prop.name}</span> |
| ${currentPropertyId === prop.id ? '<i class="fas fa-check ml-2 text-indigo-600 text-xs"></i>' : ''} |
| </div> |
| `).join('')} |
| <div class="p-2 hover:bg-gray-100 cursor-pointer text-indigo-600 text-sm flex items-center" onclick="showAddPropertyModal('${client.id}')"> |
| <i class="fas fa-plus mr-2"></i> |
| <span>Add Property</span> |
| </div> |
| </div> |
| `; |
| |
| clientList.appendChild(clientItem); |
| }); |
| } |
| |
| // Select a client |
| function selectClient(clientId) { |
| currentClientId = clientId; |
| const client = clients.find(c => c.id === clientId); |
| |
| // Update UI |
| document.getElementById('currentClientName').textContent = client.name; |
| document.getElementById('clientInfoBar').classList.remove('hidden'); |
| document.getElementById('activeClientTitle').textContent = client.name; |
| document.getElementById('activeClientProperties').textContent = `Properties: ${client.properties.length}`; |
| |
| // Show properties for this client in dropdown |
| const propertyContainer = document.getElementById(`properties-${clientId}`); |
| propertyContainer.classList.toggle('hidden'); |
| |
| // Auto-select first property if none selected |
| if (client.properties.length > 0 && !currentPropertyId) { |
| selectProperty(clientId, client.properties[0].id); |
| } |
| |
| // Close dropdown |
| document.getElementById('clientDropdown').classList.add('hidden'); |
| |
| // Update edit modal fields |
| document.getElementById('editClientName').value = client.name; |
| document.getElementById('editClientIndustry').value = client.industry; |
| document.getElementById('editClientNotes').value = client.notes; |
| } |
| |
| // Select a property |
| function selectProperty(clientId, propertyId) { |
| currentPropertyId = propertyId; |
| |
| // Update UI to show selected property |
| document.querySelectorAll('[id^="properties-"]').forEach(el => { |
| el.querySelectorAll('.fa-check').forEach(icon => { |
| icon.classList.add('hidden'); |
| }); |
| }); |
| |
| const checkIcon = document.querySelector(`[onclick="selectProperty('${clientId}', '${propertyId}')"] .fa-check`); |
| if (checkIcon) { |
| checkIcon.classList.remove('hidden'); |
| } |
| |
| // In a real app, you would load data for this property |
| console.log(`Selected property ${propertyId} for client ${clientId}`); |
| } |
| |
| // Show add client modal |
| function showAddClientModal() { |
| document.getElementById('addClientModal').classList.remove('hidden'); |
| document.getElementById('clientName').focus(); |
| } |
| |
| // Show edit client modal |
| function showEditClientModal() { |
| if (!currentClientId) return; |
| |
| const client = clients.find(c => c.id === currentClientId); |
| if (!client) return; |
| |
| document.getElementById('editClientName').value = client.name; |
| document.getElementById('editClientIndustry').value = client.industry; |
| document.getElementById('editClientNotes').value = client.notes; |
| |
| document.getElementById('editClientModal').classList.remove('hidden'); |
| } |
| |
| // Show add property modal |
| function showAddPropertyModal(clientId) { |
| if (clientId) { |
| // If called from a specific client's "Add Property" button |
| currentClientId = clientId; |
| } |
| |
| if (!currentClientId) { |
| alert('Please select a client first'); |
| return; |
| } |
| |
| // Clear form |
| document.getElementById('propertyName').value = ''; |
| document.getElementById('propertyUrl').value = ''; |
| document.getElementById('propertyType').value = 'website'; |
| document.getElementById('gaPropertyId').value = ''; |
| document.getElementById('gscPropertyId').value = ''; |
| |
| document.getElementById('addPropertyModal').classList.remove('hidden'); |
| document.getElementById('propertyName').focus(); |
| } |
| |
| // Hide any modal |
| function hideModal(modalId) { |
| document.getElementById(modalId).classList.add('hidden'); |
| } |
| |
| // Add new client |
| function addNewClient() { |
| const name = document.getElementById('clientName').value.trim(); |
| const industry = document.getElementById('clientIndustry').value.trim(); |
| const notes = document.getElementById('clientNotes').value.trim(); |
| |
| if (!name) { |
| alert('Client name is required'); |
| return; |
| } |
| |
| const newClient = { |
| id: 'client' + Date.now(), |
| name, |
| industry, |
| notes, |
| properties: [] |
| }; |
| |
| clients.push(newClient); |
| renderClientList(); |
| selectClient(newClient.id); |
| hideModal('addClientModal'); |
| } |
| |
| // Update client |
| function updateClient() { |
| if (!currentClientId) return; |
| |
| const name = document.getElementById('editClientName').value.trim(); |
| const industry = document.getElementById('editClientIndustry').value.trim(); |
| const notes = document.getElementById('editClientNotes').value.trim(); |
| |
| if (!name) { |
| alert('Client name is required'); |
| return; |
| } |
| |
| const clientIndex = clients.findIndex(c => c.id === currentClientId); |
| if (clientIndex !== -1) { |
| clients[clientIndex].name = name; |
| clients[clientIndex].industry = industry; |
| clients[clientIndex].notes = notes; |
| |
| // Update UI |
| document.getElementById('currentClientName').textContent = name; |
| document.getElementById('activeClientTitle').textContent = name; |
| renderClientList(); |
| hideModal('editClientModal'); |
| } |
| } |
| |
| // Add new property |
| function addNewProperty() { |
| if (!currentClientId) return; |
| |
| const name = document.getElementById('propertyName').value.trim(); |
| const url = document.getElementById('propertyUrl').value.trim(); |
| const type = document.getElementById('propertyType').value; |
| const gaId = document.getElementById('gaPropertyId').value.trim(); |
| const gscId = document.getElementById('gscPropertyId').value.trim(); |
| |
| if (!name || !url) { |
| alert('Property name and URL are required'); |
| return; |
| } |
| |
| const newProperty = { |
| id: 'prop' + Date.now(), |
| name, |
| url, |
| type, |
| gaId, |
| gscId |
| }; |
| |
| const clientIndex = clients.findIndex(c => c.id === currentClientId); |
| if (clientIndex !== -1) { |
| clients[clientIndex].properties.push(newProperty); |
| |
| // Update UI |
| document.getElementById('activeClientProperties').textContent = `Properties: ${clients[clientIndex].properties.length}`; |
| renderClientList(); |
| selectProperty(currentClientId, newProperty.id); |
| hideModal('addPropertyModal'); |
| } |
| } |
| |
| // Sample data for demonstration |
| const sampleData = { |
| summary: { |
| title: "Website Performance Summary", |
| subtitle: "Last 30 days compared to previous period", |
| content: ` |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> |
| <div class="bg-blue-50 p-4 rounded-lg"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-blue-700">Users</p> |
| <p class="text-2xl font-bold">12,453 <span class="text-sm font-normal text-green-600">(+8.2%)</span></p> |
| </div> |
| <div class="bg-blue-100 p-2 rounded-full"> |
| <i class="fas fa-users text-blue-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-purple-50 p-4 rounded-lg"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-purple-700">Avg. Session</p> |
| <p class="text-2xl font-bold">2:45 <span class="text-sm font-normal text-red-600">(-0.5%)</span></p> |
| </div> |
| <div class="bg-purple-100 p-2 rounded-full"> |
| <i class="fas fa-clock text-purple-600"></i> |
| </div> |
| </div> |
| </div> |
| <div class="bg-green-50 p-4 rounded-lg"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-sm text-green-700">Conversion</p> |
| <p class="text-2xl font-bold">3.2% <span class="text-sm font-normal text-green-600">(+1.1%)</span></p> |
| </div> |
| <div class="bg-green-100 p-2 rounded-full"> |
| <i class="fas fa-percentage text-green-600"></i> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="mb-6"> |
| <canvas id="summaryChart" height="200"></canvas> |
| </div> |
| |
| <div class="bg-indigo-50 p-4 rounded-lg"> |
| <h4 class="font-medium text-indigo-700 mb-2">Key Insights</h4> |
| <ul class="list-disc pl-5 space-y-1 text-sm text-gray-700"> |
| <li>Mobile traffic increased by 12% while desktop remained stable</li> |
| <li>Blog posts about "SEO tips" drove 22% of new users</li> |
| <li>Bounce rate improved by 1.8 percentage points</li> |
| <li>Conversion rates peaked on Tuesdays and Thursdays</li> |
| </ul> |
| </div> |
| ` |
| }, |
| traffic: { |
| title: "Traffic Sources Analysis", |
| subtitle: "Breakdown by channel for the last 30 days", |
| content: ` |
| <div class="mb-6"> |
| <canvas id="trafficChart" height="200"></canvas> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> |
| <div> |
| <h4 class="font-medium text-gray-700 mb-2">Top Sources</h4> |
| <div class="bg-white border border-gray-200 rounded-lg overflow-hidden"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Source</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Users</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">% Change</th> |
| </tr> |
| </thead> |
| <tbody class="divide-y divide-gray-200"> |
| <tr> |
| <td class="px-4 py-2 text-sm">Organic Search</td> |
| <td class="px-4 py-2 text-sm">6,542</td> |
| <td class="px-4 py-2 text-sm text-green-600">+12%</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">Direct</td> |
| <td class="px-4 py-2 text-sm">3,210</td> |
| <td class="px-4 py-2 text-sm text-red-600">-2%</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">Social</td> |
| <td class="px-4 py-2 text-sm">1,876</td> |
| <td class="px-4 py-2 text-sm text-green-600">+24%</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">Referral</td> |
| <td class="px-4 py-2 text-sm">825</td> |
| <td class="px-4 py-2 text-sm text-green-600">+8%</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div> |
| <h4 class="font-medium text-gray-700 mb-2">Recommendations</h4> |
| <div class="space-y-3"> |
| <div class="flex items-start"> |
| <div class="bg-blue-100 p-1 rounded-full mr-3 mt-1"> |
| <i class="fas fa-bullseye text-blue-600 text-xs"></i> |
| </div> |
| <div> |
| <p class="text-sm font-medium">Double down on social</p> |
| <p class="text-xs text-gray-600">Your social traffic is growing rapidly. Consider increasing your social media ad budget.</p> |
| </div> |
| </div> |
| <div class="flex items-start"> |
| <div class="bg-green-100 p-1 rounded-full mr-3 mt-1"> |
| <i class="fas fa-search text-green-600 text-xs"></i> |
| </div> |
| <div> |
| <p class="text-sm font-medium">Optimize for search</p> |
| <p class="text-xs text-gray-600">Create more content targeting long-tail keywords in your niche.</p> |
| </div> |
| </div> |
| <div class="flex items-start"> |
| <div class="bg-purple-100 p-1 rounded-full mr-3 mt-1"> |
| <i class="fas fa-link text-purple-600 text-xs"></i> |
| </div> |
| <div> |
| <p class="text-sm font-medium">Build partnerships</p> |
| <p class="text-xs text-gray-600">Reach out to industry websites for guest posting and backlink opportunities.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| ` |
| }, |
| keywords: { |
| title: "Top Performing Keywords", |
| subtitle: "From Google Search Console - Last 30 days", |
| content: ` |
| <div class="mb-6"> |
| <div class="flex justify-between items-center mb-3"> |
| <h4 class="font-medium text-gray-700">Keyword Performance</h4> |
| <div class="flex space-x-2"> |
| <button class="bg-indigo-100 text-indigo-700 px-3 py-1 rounded-full text-xs">Impressions</button> |
| <button class="bg-gray-100 text-gray-700 px-3 py-1 rounded-full text-xs">Clicks</button> |
| <button class="bg-gray-100 text-gray-700 px-3 py-1 rounded-full text-xs">CTR</button> |
| <button class="bg-gray-100 text-gray-700 px-3 py-1 rounded-full text-xs">Position</button> |
| </div> |
| </div> |
| <canvas id="keywordsChart" height="200"></canvas> |
| </div> |
| |
| <div class="grid grid-cols-1 gap-4"> |
| <div> |
| <h4 class="font-medium text-gray-700 mb-2">Top 10 Keywords by Clicks</h4> |
| <div class="bg-white border border-gray-200 rounded-lg overflow-hidden"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Keyword</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Clicks</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Impressions</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">CTR</th> |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Position</th> |
| </tr> |
| </thead> |
| <tbody class="divide-y divide-gray-200"> |
| <tr> |
| <td class="px-4 py-2 text-sm">seo best practices</td> |
| <td class="px-4 py-2 text-sm">1,245</td> |
| <td class="px-4 py-2 text-sm">8,762</td> |
| <td class="px-4 py-2 text-sm">14.2%</td> |
| <td class="px-4 py-2 text-sm">3.2</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">content marketing</td> |
| <td class="px-4 py-2 text-sm">876</td> |
| <td class="px-4 py-2 text-sm">5,432</td> |
| <td class="px-4 py-2 text-sm">16.1%</td> |
| <td class="px-4 py-2 text-sm">4.5</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">google analytics</td> |
| <td class="px-4 py-2 text-sm">765</td> |
| <td class="px-4 py-2 text-sm">9,123</td> |
| <td class="px-4 py-2 text-sm">8.4%</td> |
| <td class="px-4 py-2 text-sm">7.8</td> |
| </tr> |
| <tr> |
| <td class="px-4 py-2 text-sm">website optimization</td> |
| <td class="px-4 py-2 text-sm">543</td> |
| <td class="px-4 py-2 text-sm">3,210</td> |
| <td class="px-4 py-2 text-sm">16.9%</td> |
| <td class="px-4 py-2 text-sm">5.1</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
| |
| <div class="mt-6 bg-yellow-50 p-4 rounded-lg border border-yellow-200"> |
| <div class="flex items-center"> |
| <div class="bg-yellow-100 p-2 rounded-full mr-3"> |
| <i class="fas fa-lightbulb text-yellow-600"></i> |
| </div> |
| <h4 class="font-medium">Optimization Opportunity</h4> |
| </div> |
| <p class="mt-2 text-sm text-gray-700">The keyword "google analytics" has high impressions but relatively low CTR. Consider updating your meta description to be more compelling and ensure the page fully answers search intent.</p> |
| </div> |
| ` |
| } |
| }; |
| |
| // Run a predefined prompt |
| function runPrompt(promptType) { |
| if (!currentClientId || !currentPropertyId) { |
| alert('Please select a client and property first'); |
| return; |
| } |
| |
| // In a real app, this would call your LLM API with client/property context |
| // For demo, we'll use sample data |
| const data = sampleData[promptType] || { |
| title: "Analysis: " + promptType, |
| subtitle: "For " + getCurrentPropertyName(), |
| content: `<div class="typewriter">Analyzing ${getCurrentPropertyName()} data about "${promptType}". This would show real insights from your Google Analytics and Search Console data in a production environment.</div>` |
| }; |
| |
| createDataWindow(data); |
| |
| // Scroll to the new window |
| setTimeout(() => { |
| document.querySelector('#windowsContainer').lastElementChild.scrollIntoView({ |
| behavior: 'smooth' |
| }); |
| }, 100); |
| } |
| |
| // Get current property name |
| function getCurrentPropertyName() { |
| if (!currentClientId || !currentPropertyId) return 'selected property'; |
| |
| const client = clients.find(c => c.id === currentClientId); |
| if (!client) return 'selected property'; |
| |
| const property = client.properties.find(p => p.id === currentPropertyId); |
| return property ? property.name : 'selected property'; |
| } |
| |
| // Submit a custom query |
| function submitQuery() { |
| const query = document.getElementById('queryInput').value.trim(); |
| if (!query) return; |
| |
| if (!currentClientId || !currentPropertyId) { |
| alert('Please select a client and property first'); |
| return; |
| } |
| |
| // Clear input |
| document.getElementById('queryInput').value = ''; |
| |
| // Create a window with loading state |
| const loadingWindow = { |
| title: "Analyzing: " + query, |
| subtitle: "For " + getCurrentPropertyName(), |
| content: `<div class="flex items-center justify-center py-8"> |
| <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500"></div> |
| </div>` |
| }; |
| |
| const windowElement = createDataWindow(loadingWindow); |
| |
| // Simulate API call delay |
| setTimeout(() => { |
| // In a real app, you'd get actual data from your LLM API |
| const response = { |
| title: "Analysis: " + query, |
| subtitle: "For " + getCurrentPropertyName(), |
| content: `<div class="mb-4"> |
| <p>Here's the analysis for: <strong>"${query}"</strong></p> |
| <p class="text-sm text-gray-500">Client: ${getCurrentClientName()} • Property: ${getCurrentPropertyName()}</p> |
| </div> |
| <div class="bg-indigo-50 p-4 rounded-lg"> |
| <p class="text-sm">In a production environment, this would show real data visualizations and insights from your Google Analytics and Search Console data based on your specific question.</p> |
| </div> |
| <div class="mt-4"> |
| <canvas id="dynamicChart" height="200"></canvas> |
| </div> |
| <div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div class="bg-white border border-gray-200 rounded-lg p-4"> |
| <h4 class="font-medium mb-2">Key Findings</h4> |
| <ul class="list-disc pl-5 space-y-1 text-sm"> |
| <li>This would show actual findings from your data</li> |
| <li>Each insight would be relevant to your query</li> |
| <li>The LLM would generate actionable recommendations</li> |
| </ul> |
| </div> |
| <div class="bg-white border border-gray-200 rounded-lg p-4"> |
| <h4 class="font-medium mb-2">Recommendations</h4> |
| <ul class="list-disc pl-5 space-y-1 text-sm"> |
| <li>Specific actions based on your data</li> |
| <li>Prioritized by potential impact</li> |
| <li>Tailored to your business goals</li> |
| </ul> |
| </div> |
| </div>` |
| }; |
| |
| // Update the window with actual content |
| updateWindowContent(windowElement, response); |
| |
| // Create charts (demo only) |
| setTimeout(() => { |
| createDemoChart('dynamicChart', 'line'); |
| }, 100); |
| }, 1500); |
| } |
| |
| // Get current client name |
| function getCurrentClientName() { |
| if (!currentClientId) return 'selected client'; |
| |
| const client = clients.find(c => c.id === currentClientId); |
| return client ? client.name : 'selected client'; |
| } |
| |
| // Create a new data window |
| function createDataWindow(data) { |
| const template = document.getElementById('sampleWindow'); |
| const clone = template.cloneNode(true); |
| clone.id = ''; |
| clone.classList.remove('hidden'); |
| |
| // Set title and subtitle |
| clone.querySelector('#windowTitle').textContent = data.title; |
| clone.querySelector('#windowSubtitle').textContent = data.subtitle; |
| |
| // Set content |
| const contentContainer = clone.querySelector('.window-content'); |
| contentContainer.innerHTML = data.content; |
| |
| // Add to container |
| document.getElementById('windowsContainer').appendChild(clone); |
| |
| // Create charts if they exist in the content |
| if (data.content.includes('summaryChart')) { |
| createDemoChart('summaryChart', 'bar'); |
| } |
| if (data.content.includes('trafficChart')) { |
| createDemoChart('trafficChart', 'doughnut'); |
| } |
| if (data.content.includes('keywordsChart')) { |
| createDemoChart('keywordsChart', 'bar'); |
| } |
| |
| return clone; |
| } |
| |
| // Update window content |
| function updateWindowContent(windowElement, data) { |
| windowElement.querySelector('#windowTitle').textContent = data.title; |
| windowElement.querySelector('#windowSubtitle').textContent = data.subtitle; |
| windowElement.querySelector('.window-content').innerHTML = data.content; |
| } |
| |
| // Create demo charts |
| function createDemoChart(chartId, type) { |
| const ctx = document.getElementById(chartId).getContext('2d'); |
| |
| let config = {}; |
| |
| if (type === 'bar') { |
| config = { |
| type: 'bar', |
| data: { |
| labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], |
| datasets: [{ |
| label: 'Current Period', |
| data: [1200, 1900, 1700, 2100, 2300, 2500], |
| backgroundColor: 'rgba(99, 102, 241, 0.6)', |
| borderColor: 'rgba(99, 102, 241, 1)', |
| borderWidth: 1 |
| }, { |
| label: 'Previous Period', |
| data: [1000, 1700, 1500, 1900, 2000, 2200], |
| backgroundColor: 'rgba(203, 213, 225, 0.6)', |
| borderColor: 'rgba(203, 213, 225, 1)', |
| borderWidth: 1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| legend: { |
| position: 'top', |
| }, |
| tooltip: { |
| mode: 'index', |
| intersect: false, |
| } |
| }, |
| scales: { |
| y: { |
| beginAtZero: true |
| } |
| } |
| } |
| }; |
| } else if (type === 'doughnut') { |
| config = { |
| type: 'doughnut', |
| data: { |
| labels: ['Organic Search', 'Direct', 'Social', 'Referral', 'Email'], |
| datasets: [{ |
| data: [45, 25, 15, 10, 5], |
| backgroundColor: [ |
| 'rgba(99, 102, 241, 0.7)', |
| 'rgba(167, 139, 250, 0.7)', |
| 'rgba(74, 222, 128, 0.7)', |
| 'rgba(248, 113, 113, 0.7)', |
| 'rgba(251, 191, 36, 0.7)' |
| ], |
| borderWidth: 1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| legend: { |
| position: 'right', |
| } |
| } |
| } |
| }; |
| } else if (type === 'line') { |
| config = { |
| type: 'line', |
| data: { |
| labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'], |
| datasets: [{ |
| label: 'Performance Metric', |
| data: [65, 59, 80, 81], |
| fill: false, |
| backgroundColor: 'rgba(99, 102, 241, 0.6)', |
| borderColor: 'rgba(99, 102, 241, 1)', |
| tension: 0.1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| scales: { |
| y: { |
| beginAtZero: false |
| } |
| } |
| } |
| }; |
| } |
| |
| new Chart(ctx, config); |
| } |
| |
| // Voice input function |
| function voiceInput() { |
| alert("In a real implementation, this would activate the browser's speech recognition API to capture your voice query."); |
| } |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vikasrij/askanalytics2" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |