```javascript
// File: js/rta-tracker.js
// This script runs on the frontend of your website to log visitor activity.
jQuery(document).ready(function($) {
'use strict';
// Check if DNT (Do Not Track) header is set by the browser
// Note: DNT is not universally respected or implemented, but it's a good gesture.
var doNotTrack = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
if (doNotTrack === "1" || doNotTrack === "yes") {
// console.log("RTA: Do Not Track is enabled. Activity not logged.");
return; // Respect DNT
}
// Avoid logging if this is a preview or customizer view
if (typeof wp !== 'undefined' && wp.customize && wp.customize. φωτογραφίαreview && wp.customize.preview.isActive()) {
// console.log("RTA: In customizer preview. Activity not logged.");
return;
}
if (window.location.search.indexOf('preview=true') !== -1) {
// console.log("RTA: In post preview. Activity not logged.");
return;
}
var pageUrl = window.location.href;
var referrerUrl = document.referrer;
// Basic check to avoid logging if it's likely a bot or self-initiated action from common dev tools
if (typeof navigator.webdriver !== 'undefined' && navigator.webdriver) {
// console.log("RTA: WebDriver detected. Activity not logged.");
return;
}
$.ajax({
url: rtaTracker.ajax_url,
type: 'POST',
data: {
action: 'rta_log_activity',
nonce: rtaTracker.nonce,
page_url: pageUrl,
referrer_url: referrerUrl
},
success: function(response) {
// if (response.success) {
// console.log('RTA: Activity logged.');
// } else {
// console.error('RTA: Error logging activity.', response.data ? response.data.message : 'Unknown error');
// }
},
error: function(jqXHR, textStatus, errorThrown) {
// console.error('RTA: AJAX error logging activity.', textStatus, errorThrown);
}
});
});
```javascript
// File: js/rta-dashboard.js
// This script handles the dashboard widget interactions and chart rendering.
jQuery(document).ready(function($) {
'use strict';
var pageStatsChart = null;
var referrerStatsChart = null;
var liveDataInterval = null;
// Function to generate an array of distinct colors
function generateDistinctColors(count) {
var colors = [];
var baseColors = [
'#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40',
'#FFCD56', '#C9CBCF', '#3FC3A0', '#F9766C'
];
for (var i = 0; i < count; i++) {
colors.push(baseColors[i % baseColors.length]);
}
// For more than 10, you might want a more sophisticated generation algorithm
// or a larger predefined palette.
if (count > baseColors.length) {
for (var j = baseColors.length; j < count; j++) {
colors.push('hsl(' + (j * 360 / (count * 1.5) % 360) + ', 70%, 70%)');
}
}
return colors;
}
function createLegend(chartId, chartInstance) {
const legendContainer = $('#' + chartId + '-legend');
legendContainer.empty(); // Clear previous legend
const legendItems = chartInstance.data.labels.map((label, index) => {
const backgroundColor = chartInstance.data.datasets[0].backgroundColor[index];
const value = chartInstance.data.datasets[0].data[index];
const percentage = ((value / chartInstance.data.datasets[0].data.reduce((a, b) => a + b, 0)) * 100).toFixed(1);
return `
${label} (${value} - ${percentage}%)
`;
});
legendContainer.html(legendItems.join(''));
}
function fetchLiveData() {
$('#rta-live-data-container').html('' + rtaDashboard.text_loading + '
');
$.ajax({
url: rtaDashboard.ajax_url,
type: 'POST',
data: {
action: 'rta_get_live_data',
nonce: rtaDashboard.nonce_live_data
},
success: function(response) {
if (response.success && response.data.length > 0) {
var listHtml = '';
response.data.forEach(function(item) {
listHtml += '' + item.who + ' ' + rtaDashboard.text_page + ': ' + item.page + ' (' + item.time_ago + ') ';
});
listHtml += ' ';
$('#rta-live-data-container').html(listHtml);
} else {
$('#rta-live-data-container').html('' + (response.data && response.data.message ? response.data.message : rtaDashboard.text_no_data) + '
');
}
},
error: function() {
$('#rta-live-data-container').html('Error loading live data.
');
}
});
}
function fetchPageStats() {
$('#rta-page-stats-chart').hide();
$('#rta-page-stats-legend').html('' + rtaDashboard.text_loading + '
');
$.ajax({
url: rtaDashboard.ajax_url,
type: 'POST',
data: {
action: 'rta_get_page_stats',
nonce: rtaDashboard.nonce_page_stats
},
success: function(response) {
if (response.success && response.data.labels.length > 0) {
$('#rta-page-stats-chart').show();
$('#rta-page-stats-legend').empty();
var ctx = document.getElementById('rta-page-stats-chart').getContext('2d');
if (pageStatsChart) {
pageStatsChart.destroy();
}
pageStatsChart = new Chart(ctx, {
type: 'pie',
data: {
labels: response.data.labels,
datasets: [{
label: rtaDashboard.text_views,
data: response.data.counts,
backgroundColor: generateDistinctColors(response.data.labels.length),
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false // Using custom HTML legend
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.label || '';
if (label) {
label += ': ';
}
if (context.parsed !== null) {
label += context.parsed + ' ' + rtaDashboard.text_views;
}
return label;
}
}
}
}
}
});
createLegend('rta-page-stats', pageStatsChart);
} else {
$('#rta-page-stats-legend').html('' + (response.data && response.data.message ? response.data.message : rtaDashboard.text_no_data) + '
');
}
},
error: function() {
$('#rta-page-stats-legend').html('Error loading page statistics.
');
}
});
}
function fetchReferrerStats() {
$('#rta-referrer-stats-chart').hide();
$('#rta-referrer-stats-legend').html('' + rtaDashboard.text_loading + '
');
$.ajax({
url: rtaDashboard.ajax_url,
type: 'POST',
data: {
action: 'rta_get_referrer_stats',
nonce: rtaDashboard.nonce_referrer_stats
},
success: function(response) {
if (response.success && response.data.labels.length > 0) {
$('#rta-referrer-stats-chart').show();
$('#rta-referrer-stats-legend').empty();
var ctx = document.getElementById('rta-referrer-stats-chart').getContext('2d');
if (referrerStatsChart) {
referrerStatsChart.destroy();
}
referrerStatsChart = new Chart(ctx, {
type: 'pie',
data: {
labels: response.data.labels,
datasets: [{
label: rtaDashboard.text_visits,
data: response.data.counts,
backgroundColor: generateDistinctColors(response.data.labels.length),
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false // Using custom HTML legend
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.label || '';
if (label) {
label += ': ';
}
if (context.parsed !== null) {
label += context.parsed + ' ' + rtaDashboard.text_visits;
}
return label;
}
}
}
}
}
});
createLegend('rta-referrer-stats', referrerStatsChart);
} else {
$('#rta-referrer-stats-legend').html('' + (response.data && response.data.message ? response.data.message : rtaDashboard.text_no_data) + '
');
}
},
error: function() {
$('#rta-referrer-stats-legend').html('Error loading referrer statistics.
');
}
});
}
function loadAllData() {
fetchLiveData();
fetchPageStats();
fetchReferrerStats();
}
// Initial data load
loadAllData();
// Auto-refresh live data every 30 seconds
if(liveDataInterval) clearInterval(liveDataInterval);
liveDataInterval = setInterval(fetchLiveData, 30000);
// Refresh button
$('#rta-refresh-button').on('click', function() {
loadAllData();
});
// Maximize/Minimize button
$('#rta-maximize-button').on('click', function() {
$('#rta_dashboard_widget').toggleClass('rta-maximized');
$(this).hide();
$('#rta-minimize-button').show();
// Trigger chart redraw if necessary, as canvas size might change
if (pageStatsChart) pageStatsChart.resize();
if (referrerStatsChart) referrerStatsChart.resize();
});
$('#rta-minimize-button').on('click', function() {
$('#rta_dashboard_widget').toggleClass('rta-maximized');
$(this).hide();
$('#rta-maximize-button').show();
if (pageStatsChart) pageStatsChart.resize();
if (referrerStatsChart) referrerStatsChart.resize();
});
});
```css
/* File: css/rta-dashboard.css */
/* Styles for the Real-Time Analytics dashboard widget. */
#rta_dashboard_widget .inside {
padding: 0;
margin: 0;
}
#rta-widget-container {
padding: 15px;
position: relative;
}
#rta-maximize-button, #rta-minimize-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
}
#rta-minimize-button {
display: none; /* Initially hidden */
}
#rta-refresh-button {
position: absolute;
top: 10px;
right: 120px; /* Adjust if maximize button text changes */
z-index: 10;
}
.rta-section {
margin-bottom: 25px;
padding: 10px;
border: 1px solid #e5e5e5;
border-radius: 4px;
background-color: #fff;
}
.rta-section h3 {
margin-top: 0;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
font-size: 1.1em;
color: #333;
}
#rta-live-data-container {
max-height: 200px;
overflow-y: auto;
font-size: 0.9em;
}
.rta-live-list {
list-style: none;
padding-left: 0;
margin: 0;
}
.rta-live-list li {
padding: 5px 0;
border-bottom: 1px dashed #f0f0f0;
}
.rta-live-list li:last-child {
border-bottom: none;
}
.rta-live-list li strong {
color: #2271b1;
}
.rta-live-list li em {
color: #777;
font-size: 0.9em;
}
.rta-charts-container {
display: flex;
flex-wrap: wrap; /* Allow wrapping on smaller screens */
gap: 20px; /* Space between charts */
}
.rta-chart-wrapper {
flex: 1; /* Each chart wrapper takes equal space */
min-width: 300px; /* Minimum width before wrapping */
}
.rta-chart-container {
position: relative;
height: 300px; /* Fixed height for chart canvas */
width: 100%;
margin-bottom: 15px;
}
.rta-legend-container {
font-size: 0.85em;
max-height: 150px;
overflow-y: auto;
}
.rta-legend-item {
display: flex;
align-items: center;
margin-bottom: 4px;
}
.rta-legend-color-box {
width: 12px;
height: 12px;
margin-right: 8px;
border: 1px solid #ccc;
display: inline-block;
}
.rta-legend-label {
color: #555;
}
/* Maximized state for the widget */
#rta_dashboard_widget.rta-maximized {
position: fixed !important;
top: 40px !important; /* Below admin bar */
left: 20px !important;
right: 20px !important;
bottom: 20px !important;
width: auto !important; /* Override default widget width */
height: auto !important; /* Override default widget height */
z-index: 99998 !important; /* Below admin bar modals but above other content */
background-color: #f0f0f1; /* WordPress dashboard background */
border: 1px solid #c3c4c7;
box-shadow: 0 0 15px rgba(0,0,0,0.2);
overflow-y: auto;
}
#rta_dashboard_widget.rta-maximized .inside {
height: calc(100% - 30px); /* Adjust based on padding */
overflow-y: auto;
}
#rta_dashboard_widget.rta-maximized #rta-widget-container {
height: 100%;
display: flex;
flex-direction: column;
}
#rta_dashboard_widget.rta-maximized .rta-charts-container {
flex-grow: 1; /* Allow charts to take available space */
min-height: 350px; /* Ensure charts have enough space when maximized */
}
#rta_dashboard_widget.rta-maximized .rta-chart-container {
height: 350px; /* Larger charts when maximized */
}
.rta-footer-note {
font-size: 0.8em;
color: #777;
margin-top: 20px;
text-align: center;
}
/* Loading/No Data messages */
#rta-live-data-container p,
.rta-legend-container p {
text-align: center;
color: #888;
padding: 20px;
}
Product Eight – Luxury Wine Products
Skip to content
Product Eight $ 9.99
Find creative ways to provide as much information as possible to properly inform the shopper without overwhelming them with words.
Your product page needs to address any potential concerns or hesitations your potential buyer might have. Will these pants fit? How long is the battery life? Can I return this product? Are sizes accurate?