login
Terms | Privacy Policy | (c) Copyright 2026 Yehaa Trading Trust (T/A Indie Pulse). All rights reserved.
To transform the music industry — putting the money and power back where it belongs: with the artists.
All Indie—no labels, no AI.
Powered by: Woo
login
First Name: ${user.name || 'N/A'}
Last Name: ${user.lastName || 'N/A'}
Email Address: ${user.email || 'N/A'}
Phone Number: ${user.number || 'N/A'}
Stats unavailable
'; playsGraph.wrapper.innerHTML += 'Stats unavailable
'; topSongsGraph.wrapper.innerHTML += 'Stats unavailable
'; return; } try { const remoteDb = woo.getDB(visitsDbId + "CouchDB"); if (remoteDb) { await visitsDb.replicate.from(remoteDb, { retry: true }); console.log("[STATS] Pulled latest data"); } const now = new Date(); const thirtyDaysAgo = new Date(now); thirtyDaysAgo.setDate(now.getDate() - 30); const labels = []; for (let i = 29; i >= 0; i--) { const d = new Date(now); d.setDate(d.getDate() - i); labels.push(d.toISOString().slice(0, 10)); } // 1. Daily visits (unchanged) const visitsResult = await visitsDb.query('visits/daily_by_artist', { startkey: [userId], endkey: [userId, {}], reduce: true, group_level: 2 }); const dayMapVisits = Object.fromEntries(labels.map(d => [d, 0])); visitsResult.rows?.forEach(row => { const dateStr = row.key?.[1]; if (dateStr in dayMapVisits) dayMapVisits[dateStr] = row.value || 0; }); const visitsData = labels.map(d => dayMapVisits[d]); // 2. Daily plays (unchanged) const playsResult = await visitsDb.query('visits/daily_song_plays_by_artist', { startkey: [userId], endkey: [userId, {}], reduce: true, group_level: 2 }); const dayMapPlays = Object.fromEntries(labels.map(d => [d, 0])); playsResult.rows?.forEach(row => { const dateStr = row.key?.[1]; if (dateStr in dayMapPlays) dayMapPlays[dateStr] = row.value || 0; }); const playsData = labels.map(d => dayMapPlays[d]); // 3. All-time top songs – updated to legit vs non-legit, grouped by name const totalResult = await visitsDb.query('visits/song_plays_daily_by_artist_and_song', { startkey: [userId], endkey: [userId, {}], reduce: true, group_level: 2 }); const legitResult = await visitsDb.query('visits/song_plays_daily_by_artist_and_song_legit', { startkey: [userId], endkey: [userId, {}], reduce: true, group_level: 2 }); const songData = {}; totalResult.rows?.forEach(row => { if (!row.key || row.key.length < 2) return; const songName = row.key[1]; const count = row.value?.count ?? row.value ?? 0; if (!songData[songName]) songData[songName] = { name: songName, total: 0, legit: 0 }; songData[songName].total += count; }); legitResult.rows?.forEach(row => { if (!row.key || row.key.length < 2) return; const songName = row.key[1]; const count = row.value?.count ?? row.value ?? 0; if (!songData[songName]) songData[songName] = { name: songName, total: 0, legit: 0 }; songData[songName].legit += count; }); // Calculate non-legit Object.values(songData).forEach(s => { s.nonLegit = Math.max(0, s.total - s.legit); }); // Sort and take top 10 const sortedTotals = Object.values(songData) .sort((a, b) => b.total - a.total) .slice(0, 10); const topSongNames = sortedTotals.map(s => s.name); // Datasets for legit and non-legit (legit first for green on left) const datasets = [ { label: 'Legit Listener Plays', data: sortedTotals.map(s => s.legit), backgroundColor: 'rgba(75, 192, 192, 0.7)', // teal borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }, { label: 'Non-Legit Plays (self / admin / bots)', data: sortedTotals.map(s => s.nonLegit), backgroundColor: 'rgba(255, 99, 132, 0.7)', // pink borderColor: 'rgba(255, 99, 132, 1)', borderWidth: 1 } ]; // Helper to safely (re)create chart function renderChart(canvas, config) { if (canvas.chartInstance) canvas.chartInstance.destroy(); canvas.chartInstance = new Chart(canvas.getContext('2d'), config); } // Visits line (unchanged) renderChart(visitsGraph.canvas, { type: 'line', data: { labels, datasets: [{ label: 'Visits', data: visitsData, borderColor: '#00c853', backgroundColor: 'rgba(0,200,83,0.1)', tension: 0.4, fill: true, pointRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } }, x: { ticks: { maxTicksLimit: 10 } } } } }); // Plays line (unchanged) renderChart(playsGraph.canvas, { type: 'line', data: { labels, datasets: [{ label: 'Plays', data: playsData, borderColor: '#ff5722', backgroundColor: 'rgba(255,87,34,0.1)', tension: 0.4, fill: true, pointRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } }, x: { ticks: { maxTicksLimit: 10 } } } } }); // Top songs – grouped horizontal bars (separate bars one on top of the other) renderChart(topSongsGraph.canvas, { type: 'bar', data: { labels: topSongNames, datasets: datasets }, options: { indexAxis: 'y', responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top', labels: { boxWidth: 12, padding: 15, font: { size: 12 } } }, title: { display: false } }, scales: { x: { stacked: false, beginAtZero: true, title: { display: true, text: 'Plays (all time)' } }, y: { stacked: false, ticks: { font: { size: 12 } } } }, elements: { bar: { barPercentage: 0.8, categoryPercentage: 0.9 } } } }); } catch (err) { console.error("Stats loading error:", err); visitsGraph.wrapper.innerHTML += 'Error loading data
'; playsGraph.wrapper.innerHTML += 'Error loading data
'; topSongsGraph.wrapper.innerHTML += 'Error loading data
'; } } loadAndRenderStats(); } } // Run immediately loadAndDisplayProfile(); gkxwvsqf_2026030224611_2_Global.unload = () => { console.log("Unloaded gkxwvsqf_2026030224611_2"); }; return gkxwvsqf_2026030224611_2_Global; })();With a growing awareness of on-line privacy and security issues, further tightening of the spam laws worldwide and the need for businesses to have more robust collection of data systems in place, Woo has risen to the challenge by creating a universal ID for users on the platform - called a Woo ID.
The Woo ID provides you with the security that Woo is dedicated, and bound by law, to ensure your information is kept private and that all anti-spam laws are adhered to. Every user added to a Woo website gets to verify their email address. This ensures issues with data entry and out-of-date email accounts are spotted early.
The Woo ID universal ID is the market leader: creating a safe and spam free environment for you.
Read more about Woo and their Privacy Policy
"; var message = $("With a growing awareness of on-line privacy and security issues, further tightening of the spam laws worldwide and the need for businesses to have more robust collection of data systems in place, Woo has risen to the challenge by creating a universal ID for users on the platform - called a Woo ID.
The Woo ID provides you with the security that Woo is dedicated, and bound by law, to ensure your information is kept private and that all anti-spam laws are adhered to. Every user added to a Woo website gets to verify their email address. This ensures issues with data entry and out-of-date email accounts are spotted early.
The Woo ID universal ID is the market leader: creating a safe and spam free environment for you.
Read more about Woo and their Privacy Policy
"; var message = $("

