askanalytics2 / index.html
vikasrij's picture
Add 2 files
fd44b34 verified
<!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 -->
<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">
<!-- Client list will be populated here -->
</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 Content -->
<main class="flex-1 container mx-auto p-4 grid grid-cols-1 lg:grid-cols-4 gap-6">
<!-- Left Sidebar - Quick Prompts -->
<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>
<!-- Main Content Area -->
<div class="lg:col-span-3 space-y-6">
<!-- Client Info Bar -->
<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>
<!-- Query Input -->
<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>
<!-- Data Windows Container -->
<div id="windowsContainer" class="space-y-6">
<!-- Welcome Window -->
<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>
<!-- Sample Data Window (hidden by default) -->
<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">
<!-- Content will be dynamically inserted here -->
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- Add Client Modal -->
<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>
<!-- Edit Client Modal -->
<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>
<!-- Add Property Modal -->
<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>