Local vs. Global Product Demand Analyzer

Local vs. Global Product Demand Analyzer

Compare market interest for your product niche at different scales.

Enter a niche and region to begin your analysis.

Analyzing demand data...

'; placeholder.classList.remove('hidden'); resultsContainer.classList.add('hidden'); setTimeout(() => { const analysisData = generateSimulatedData(nicheQuery, regionInput.value.trim()); renderResults(analysisData); }, 1500); }; const renderResults = (data) => { placeholder.classList.add('hidden'); resultsContainer.classList.remove('hidden'); nicheTitle.textContent = data.niche; // Top Markets topMarketsList.innerHTML = data.topMarkets.map(market => `
  • ${market.country}
  • `).join(''); renderScoreChart(data.region, data.scores.local, data.scores.global); renderTrendChart(data.trends.local, data.trends.global); }; // --- Data Simulation --- const hashCode = (str) => { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash |= 0; // Convert to 32bit integer } return Math.abs(hash); }; const generateSimulatedData = (niche, region) => { const seed = hashCode(niche.toLowerCase()); let localSeed = hashCode(region.toLowerCase()); const seededRandom = (s) => { const x = Math.sin(s) * 10000; return x - Math.floor(x); }; const globalScore = Math.floor(seededRandom(seed) * 60 + 40); // 40-100 const localScore = Math.floor(seededRandom(seed + localSeed) * 80 + 20); // 20-100 const globalTrend = Array.from({length: 12}, (_, i) => Math.floor(seededRandom(seed + i) * globalScore + 10)); const localTrend = Array.from({length: 12}, (_, i) => Math.floor(seededRandom(seed + localSeed + i) * localScore + 5)); const countries = ["USA", "China", "Germany", "UK", "Japan", "India", "France", "Canada"]; const topMarkets = countries.slice(0, 5).map((c, i) => ({ country: c, share: Math.floor(seededRandom(seed + i * 10) * 70 + 30) })).sort((a,b) => b.share - a.share); return { niche, region, scores: { local: localScore, global: globalScore }, trends: { local: localTrend, global: globalTrend }, topMarkets }; }; // --- Chart Rendering --- const renderScoreChart = (region, localScore, globalScore) => { const ctx = document.getElementById('score-bar-chart').getContext('2d'); if (scoreChartInstance) scoreChartInstance.destroy(); scoreChartInstance = new Chart(ctx, { type: 'bar', data: { labels: [region, 'Global'], datasets: [{ label: 'Demand Score', data: [localScore, globalScore], backgroundColor: ['rgba(59, 130, 246, 0.7)', 'rgba(75, 85, 99, 0.7)'], borderColor: ['rgba(59, 130, 246, 1)', 'rgba(75, 85, 99, 1)'], borderWidth: 1 }] }, options: { indexAxis: 'y', responsive: true, scales: { x: { beginAtZero: true, max: 100 } }, plugins: { legend: { display: false } } } }); }; const renderTrendChart = (localData, globalData) => { const ctx = document.getElementById('trend-line-chart').getContext('2d'); if (trendChartInstance) trendChartInstance.destroy(); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; trendChartInstance = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [ { label: 'Local Trend', data: localData, borderColor: 'rgba(59, 130, 246, 1)', backgroundColor: 'rgba(59, 130, 246, 0.2)', fill: true, tension: 0.3 }, { label: 'Global Trend', data: globalData, borderColor: 'rgba(75, 85, 99, 1)', backgroundColor: 'rgba(75, 85, 99, 0.2)', fill: true, tension: 0.3 } ] }, options: { responsive: true, scales: { y: { beginAtZero: true, max: 100 } }, } }); }; const handleDownloadPdf = async () => { const pdfContentEl = document.getElementById('pdf-content'); if (!pdfContentEl || !scoreChartInstance || !trendChartInstance) return; // Populate PDF document.getElementById('pdf-niche-title').textContent = nicheInput.value; document.getElementById('pdf-timestamp').textContent = new Date().toLocaleString('en-US'); document.getElementById('pdf-top-markets').innerHTML = topMarketsList.outerHTML; // Convert charts to images document.getElementById('pdf-score-chart-img').src = scoreChartInstance.toBase64Image(); document.getElementById('pdf-trend-chart-img').src = trendChartInstance.toBase64Image(); pdfContentEl.classList.remove('hidden'); await new Promise(resolve => setTimeout(resolve, 100)); html2canvas(pdfContentEl, { scale: 2 }).then(canvas => { pdfContentEl.classList.add('hidden'); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const margin = 40; const imgWidth = pdfWidth - (margin * 2); const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.addImage(imgData, 'PNG', margin, margin, imgWidth, imgHeight); pdf.save(`${nicheInput.value.replace(/\s+/g, '-')}-demand-analysis.pdf`); }).catch(err => { console.error("Error generating PDF:", err); pdfContentEl.classList.add('hidden'); }); }; // --- Event Listeners --- analyzeBtn.addEventListener('click', handleAnalysis); pdfBtn.addEventListener('click', handleDownloadPdf); });
    Scroll to Top