Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions assets/css/analytics.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Mailchimp Analytics Page Styles
*
* @package Mailchimp
*/

/* Filters bar */
.mailchimp-sf-analytics-wrapper {
max-width: 1200px;
margin: 20px 0;
}

.mailchimp-sf-analytics-filters {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: 16px;
padding: 20px;
background: #fff;
border: 1px solid #dcdcde;
border-radius: 4px;
margin-bottom: 20px;
}

.mailchimp-sf-analytics-filter-group {
display: flex;
flex-direction: column;
gap: 4px;
}

.mailchimp-sf-analytics-filter-group label {
font-size: 12px;
font-weight: 600;
color: #1d2327;
text-transform: uppercase;
letter-spacing: 0.5px;
}

.mailchimp-sf-analytics-filter-group select,
.mailchimp-sf-analytics-filter-group input[type="date"] {
min-width: 180px;
height: 36px;
padding: 0 8px;
border: 1px solid #8c8f94;
border-radius: 4px;
font-size: 14px;
color: #1d2327;
background-color: #fff;
}

.mailchimp-sf-analytics-filter-group select:focus,
.mailchimp-sf-analytics-filter-group input[type="date"]:focus {
border-color: #007cba;
box-shadow: 0 0 0 1px #007cba;
outline: none;
}

/* Custom date range row */
.mailchimp-sf-custom-dates {
flex-direction: row;
align-items: flex-end;
gap: 8px;
}

.mailchimp-sf-custom-dates label {
align-self: center;
}

/* Resolved date range display */
.mailchimp-sf-analytics-date-display {
margin-left: auto;
align-self: center;
font-size: 14px;
color: #50575e;
font-style: italic;
}

/* Content area */
.mailchimp-sf-analytics-content {
padding: 24px;
background: #fff;
border: 1px solid #dcdcde;
border-radius: 4px;
min-height: 200px;
margin-bottom: 20px;
}

.mailchimp-sf-analytics-placeholder {
display: flex;
align-items: center;
justify-content: center;
min-height: 200px;
color: #8c8f94;
font-size: 15px;
}

/* Deep link */
.mailchimp-sf-analytics-deep-link {
margin-top: 16px;
}

.mailchimp-sf-analytics-deep-link a {
display: inline-flex;
align-items: center;
gap: 6px;
}

.mailchimp-sf-analytics-deep-link .dashicons {
font-size: 16px;
width: 16px;
height: 16px;
line-height: 16px;
}

/* Responsive */
@media screen and (max-width: 782px) {
.mailchimp-sf-analytics-filters {
flex-direction: column;
align-items: stretch;
}

.mailchimp-sf-analytics-date-display {
margin-left: 0;
}

.mailchimp-sf-custom-dates {
flex-direction: column;
align-items: stretch;
}

.mailchimp-sf-analytics-filter-group select,
.mailchimp-sf-analytics-filter-group input[type="date"] {
min-width: auto;
width: 100%;
}
}
121 changes: 121 additions & 0 deletions assets/js/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* Mailchimp Analytics Page JavaScript
*
* @package Mailchimp
*/

(function () {
const dateRangeSelect = document.getElementById('mailchimp-sf-date-range');
const customDates = document.querySelector('.mailchimp-sf-custom-dates');
const dateFrom = document.getElementById('mailchimp-sf-date-from');
const dateTo = document.getElementById('mailchimp-sf-date-to');
const listFilter = document.getElementById('mailchimp-sf-list-filter');
const resolvedDisplay = document.getElementById('mailchimp-sf-resolved-date-range');

/**
* Format a Date object to a human-readable string.
*
* @param {Date} date Date to format.
* @returns {string} Formatted date string.
*/
function formatDate(date) {
return date.toLocaleDateString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
});
}

/**
* Get the resolved date range based on current filter selection.
*
* @returns {{ from: Date, to: Date }|null} Date range or null.
*/
function getDateRange() {
const { value } = dateRangeSelect;
let to = new Date();
let from;

if (value === 'custom') {
if (!dateFrom.value || !dateTo.value) {
return null;
}
from = new Date(`${dateFrom.value}T00:00:00`);
to = new Date(`${dateTo.value}T23:59:59`);
return { from, to };
}

const days = parseInt(value, 10);
from = new Date();
from.setDate(from.getDate() - days);
return { from, to };
}

/**
* Update the resolved date range display text.
*/
function updateResolvedDateRange() {
const range = getDateRange();
if (range) {
resolvedDisplay.textContent = `${formatDate(range.from)} \u2013 ${formatDate(range.to)}`;
} else {
resolvedDisplay.textContent = '';
}
}

/**
* Toggle visibility of custom date inputs.
*/
function toggleCustomDates() {
const isCustom = dateRangeSelect.value === 'custom';
customDates.style.display = isCustom ? 'flex' : 'none';
}

/**
* Refresh analytics sections when filters change.
*/
function refreshAnalytics() {
updateResolvedDateRange();

const range = getDateRange();
const listId = listFilter ? listFilter.value : '';

if (!range) {
return;
}

// Dispatch a custom event so other scripts can listen for filter changes.
const event = new CustomEvent('mailchimp-analytics-refresh', {
detail: {
from: range.from.toISOString(),
to: range.to.toISOString(),
listId,
},
});
document.dispatchEvent(event);
}

// Bind events.
if (dateRangeSelect) {
dateRangeSelect.addEventListener('change', function () {
toggleCustomDates();
refreshAnalytics();
});
}

if (dateFrom) {
dateFrom.addEventListener('change', refreshAnalytics);
}

if (dateTo) {
dateTo.addEventListener('change', refreshAnalytics);
}

if (listFilter) {
listFilter.addEventListener('change', refreshAnalytics);
}

// Initialize on load.
toggleCustomDates();
updateResolvedDateRange();
})();
89 changes: 89 additions & 0 deletions includes/admin/templates/analytics.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* Analytics page template
*
* @package Mailchimp
*/

$user = get_option( 'mc_user' );
$is_logged_in = ! ( ! $user || ( ! get_option( 'mc_api_key' ) && ! mailchimp_sf_get_access_token() ) );
$lists = get_option( 'mailchimp_sf_lists', array() );
$current_list = get_option( 'mc_list_id', '' );
$dc = get_option( 'mc_datacenter', '' );
?>
<div id="mailchimp-sf-analytics-page">
<?php require_once MCSF_DIR . 'includes/admin/templates/header.php'; ?>

<div class="mailchimp-sf-settings-page-hero-wrapper">
<div class="mailchimp-sf-settings-page-hero">
<div class="mailchimp-sf-settings-page-hero-title-wrapper">
<h1 class="mailchimp-sf-settings-page-hero-title">
<?php esc_html_e( 'Analytics', 'mailchimp' ); ?>
</h1>
<p class="mailchimp-sf-settings-page-hero-description">
<?php esc_html_e( 'View audience analytics and insights for your Mailchimp lists.', 'mailchimp' ); ?>
</p>
</div>
</div>
</div>

<div class="wrap">
<div class="mailchimp-sf-analytics-wrapper">
<div class="mailchimp-sf-analytics-filters">
<div class="mailchimp-sf-analytics-filter-group">
<label for="mailchimp-sf-date-range"><?php esc_html_e( 'Date Range', 'mailchimp' ); ?></label>
<select id="mailchimp-sf-date-range">
<option value="7"><?php esc_html_e( 'Last 7 days', 'mailchimp' ); ?></option>
<option value="30" selected><?php esc_html_e( 'Last 30 days', 'mailchimp' ); ?></option>
<option value="90"><?php esc_html_e( 'Last 90 days', 'mailchimp' ); ?></option>
<option value="180"><?php esc_html_e( 'Last 6 months', 'mailchimp' ); ?></option>
<option value="365"><?php esc_html_e( 'Last year', 'mailchimp' ); ?></option>
<option value="custom"><?php esc_html_e( 'Custom', 'mailchimp' ); ?></option>
</select>
</div>

<div class="mailchimp-sf-analytics-filter-group mailchimp-sf-custom-dates" style="display: none;">
<label for="mailchimp-sf-date-from"><?php esc_html_e( 'From', 'mailchimp' ); ?></label>
<input type="date" id="mailchimp-sf-date-from" />
<label for="mailchimp-sf-date-to"><?php esc_html_e( 'To', 'mailchimp' ); ?></label>
<input type="date" id="mailchimp-sf-date-to" />
</div>

<div class="mailchimp-sf-analytics-filter-group">
<label for="mailchimp-sf-list-filter"><?php esc_html_e( 'List', 'mailchimp' ); ?></label>
<select id="mailchimp-sf-list-filter">
<?php if ( ! empty( $lists ) ) : ?>
<?php foreach ( $lists as $list ) : ?>
<option value="<?php echo esc_attr( $list['id'] ); ?>" <?php selected( $list['id'], $current_list ); ?>>
<?php echo esc_html( $list['name'] ); ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>

<div class="mailchimp-sf-analytics-date-display">
<span id="mailchimp-sf-resolved-date-range"></span>
</div>
</div>

<div class="mailchimp-sf-analytics-content" id="mailchimp-sf-analytics-content">
<div class="mailchimp-sf-analytics-placeholder">
<p><?php esc_html_e( 'Select a date range and list to view analytics.', 'mailchimp' ); ?></p>
</div>
</div>

<?php if ( $dc ) : ?>
<div class="mailchimp-sf-analytics-deep-link">
<a href="<?php echo esc_url( 'https://' . $dc . '.admin.mailchimp.com/analytics/audience-analytics/' ); ?>"
target="_blank"
rel="noopener noreferrer"
class="mailchimp-sf-button btn-secondary">
<?php esc_html_e( 'View detailed analytics in Mailchimp', 'mailchimp' ); ?>
<span class="dashicons dashicons-external" aria-hidden="true"></span>
</a>
</div>
<?php endif; ?>
</div>
</div>
</div>
10 changes: 10 additions & 0 deletions includes/class-mailchimp-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,16 @@ public function add_admin_menu_pages() {
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1Mi4wMyA1NSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5Bc3NldCAxPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iTGF5ZXJfMS0yIiBkYXRhLW5hbWU9IkxheWVyIDEiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTExLjY0LDI4LjU0YTQuNzUsNC43NSwwLDAsMC0xLjE3LjA4Yy0yLjc5LjU2LTQuMzYsMi45NC00LjA1LDZhNi4yNCw2LjI0LDAsMCwwLDUuNzIsNS4yMSw0LjE3LDQuMTcsMCwwLDAsLjgtLjA2YzIuODMtLjQ4LDMuNTctMy41NSwzLjEtNi41N0MxNS41MSwyOS44MywxMy4yMSwyOC42MywxMS42NCwyOC41NFptMi43Nyw4LjA3YTEuMTcsMS4xNywwLDAsMS0xLjEuNTUsMS41MywxLjUzLDAsMCwxLTEuMzctMS41OEE0LDQsMCwwLDEsMTIuMjMsMzRhMS40NCwxLjQ0LDAsMCwwLS41NS0xLjc0LDEuNDgsMS40OCwwLDAsMC0xLjEyLS4yMSwxLjQ0LDEuNDQsMCwwLDAtLjkyLjY0LDMuMzksMy4zOSwwLDAsMC0uMzQuNzlsMCwuMTFjLS4xMy4zNC0uMzMuNDUtLjQ3LjQzcy0uMTYtLjA1LS4yMS0uMjFhMywzLDAsMCwxLC43OC0yLjU1LDIuNDYsMi40NiwwLDAsMSwyLjExLS43NiwyLjUsMi41LDAsMCwxLDEuOTEsMS4zOSwzLjE5LDMuMTksMCwwLDEtLjIzLDIuODJsLS4wOS4yQTEuMTYsMS4xNiwwLDAsMCwxMywzNmEuNzQuNzQsMCwwLDAsLjYzLjMyLDEuMzgsMS4zOCwwLDAsMCwuMzQsMGMuMTUsMCwuMy0uMDcuMzksMEEuMjQuMjQsMCwwLDEsMTQuNDEsMzYuNjFaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNTEsMzMuODhhMy44NCwzLjg0LDAsMCwwLTEuMTUtMWwtLjExLS4zNy0uMTQtLjQyYTUuNTcsNS41NywwLDAsMCwuNS0zLjMyLDUuNDMsNS40MywwLDAsMC0xLjU0LTMsMTAuMDksMTAuMDksMCwwLDAtNC4yNC0yLjI2YzAtLjY3LDAtMS40My0uMDYtMS45YTEyLjgzLDEyLjgzLDAsMCwwLS40OS0zLjI1LDEwLjQ2LDEwLjQ2LDAsMCwwLTEuMy0yLjkyYzIuMTQtMi41NiwzLjI5LTUuMjEsMy4yOS03LjU3LDAtMy44My0zLTYuMy03LjU5LTYuM2ExOS4zLDE5LjMsMCwwLDAtNy4yMiwxLjZsLS4zNC4xNEwyOC43LDEuNTJBNi4zMSw2LjMxLDAsMCwwLDI0LjQzLDAsMTQuMDcsMTQuMDcsMCwwLDAsMTcuNiwyLjJhMzYuOTMsMzYuOTMsMCwwLDAtNi43OCw1LjIxYy00LjYsNC4zOC04LjMsOS42My05LjkxLDE0QTEyLjUxLDEyLjUxLDAsMCwwLDAsMjYuNTRhNi4xNiw2LjE2LDAsMCwwLDIuMTMsNC40bC43OC42NkExMC40NCwxMC40NCwwLDAsMCwyLjc0LDM1YTkuMzYsOS4zNiwwLDAsMCwzLjIxLDYsMTAsMTAsMCwwLDAsNS4xMywyLjQzLDIwLjE5LDIwLjE5LDAsMCwwLDcuMzEsOEEyMy4zMywyMy4zMywwLDAsMCwzMC4xNyw1NUgzMWEyMy4yNywyMy4yNywwLDAsMCwxMi0zLjE2LDE5LjEsMTkuMSwwLDAsMCw3LjgyLTkuMDZsMCwwQTE2Ljg5LDE2Ljg5LDAsMCwwLDUyLDM3LjIzLDUuMTcsNS4xNywwLDAsMCw1MSwzMy44OFptLTEuNzgsOC4yMWMtMyw3LjI5LTEwLjMsMTEuMzUtMTksMTEuMDktOC4wNi0uMjQtMTQuOTQtNC41LTE4LTExLjQzYTcuOTQsNy45NCwwLDAsMS01LjEyLTIuMDYsNy41Niw3LjU2LDAsMCwxLTIuNjEtNC44NUE4LjMxLDguMzEsMCwwLDEsNSwzMUwzLjMyLDI5LjU2Qy00LjQyLDIzLDE5Ljc3LTMuODYsMjcuNTEsMi44OWwyLjY0LDIuNTgsMS40NC0uNjFjNi43OS0yLjgxLDEyLjMtMS40NSwxMi4zLDMsMCwyLjMzLTEuNDgsNS4wNS0zLjg2LDcuNTJhNy41NCw3LjU0LDAsMCwxLDIsMy40OCwxMSwxMSwwLDAsMSwuNDIsMi44MmMwLDEsLjA5LDMuMTYuMDksMy4ybDEsLjI3QTguNjQsOC42NCwwLDAsMSw0Ny4yLDI3YTMuNjYsMy42NiwwLDAsMSwxLjA2LDIuMDZBNCw0LDAsMCwxLDQ3LjU1LDMyLDEwLjE1LDEwLjE1LDAsMCwxLDQ4LDMzLjA4Yy4yLjY0LjM1LDEuMTguMzcsMS4yNS43NCwwLDEuODkuODUsMS44OSwyLjg5QTE1LjI5LDE1LjI5LDAsMCwxLDQ5LjE4LDQyLjA5WiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQ4LDM2YTEuMzYsMS4zNiwwLDAsMC0uODYtLjE2LDExLjc2LDExLjc2LDAsMCwwLS44Mi0yLjc4QTE3Ljg5LDE3Ljg5LDAsMCwxLDQwLjQ1LDM2YTIzLjY0LDIzLjY0LDAsMCwxLTcuODEuODRjLTEuNjktLjE0LTIuODEtLjYzLTMuMjMuNzRhMTguMywxOC4zLDAsMCwwLDgsLjgxLjE0LjE0LDAsMCwxLC4xNi4xMy4xNS4xNSwwLDAsMS0uMDkuMTVzLTMuMTQsMS40Ni04LjE0LS4wOGEyLjU4LDIuNTgsMCwwLDAsMS44MywxLjkxLDguMjQsOC4yNCwwLDAsMCwxLjQ0LjM5YzYuMTksMS4wNiwxMi0yLjQ3LDEzLjI3LTMuMzYuMS0uMDcuMTYsMCwuMDguMTJsLS4xMy4xOGMtMS41OSwyLjA2LTUuODgsNC40NC0xMS40NSw0LjQ0LTIuNDMsMC00Ljg2LS44Ni01Ljc1LTIuMTctMS4zOC0yLS4wNy01LDIuMjQtNC43MWwxLC4xMWEyMS4xMywyMS4xMywwLDAsMCwxMC41LTEuNjhjMy4xNS0xLjQ2LDQuMzQtMy4wNyw0LjE2LTQuMzdBMS44NywxLjg3LDAsMCwwLDQ2LDI4LjM0YTYuOCw2LjgsMCwwLDAtMy0xLjQxYy0uNS0uMTQtLjg0LS4yMy0xLjItLjM1LS42NS0uMjEtMS0uMzktMS0xLjYxLDAtLjUzLS4xMi0yLjQtLjE2LTMuMTYtLjA2LTEuMzUtLjIyLTMuMTktMS4zNi00YTEuOTIsMS45MiwwLDAsMC0xLS4zMSwxLjg2LDEuODYsMCwwLDAtLjU4LjA2LDMuMDcsMy4wNywwLDAsMC0xLjUyLjg2LDUuMjQsNS4yNCwwLDAsMS00LDEuMzJjLS44LDAtMS42NS0uMTYtMi42Mi0uMjJsLS41NywwYTUuMjIsNS4yMiwwLDAsMC01LDQuNTdjLS41NiwzLjgzLDIuMjIsNS44MSwzLDdhMSwxLDAsMCwxLC4yMi41Mi44My44MywwLDAsMS0uMjguNTVoMGE5LjgsOS44LDAsMCwwLTIuMTYsOS4yLDcuNTksNy41OSwwLDAsMCwuNDEsMS4xMmMyLDQuNzMsOC4zLDYuOTMsMTQuNDMsNC45M2ExNS4wNiwxNS4wNiwwLDAsMCwyLjMzLTEsMTIuMjMsMTIuMjMsMCwwLDAsMy41Ny0yLjY3LDEwLjYxLDEwLjYxLDAsMCwwLDMtNS44MkM0OC42LDM2LjcsNDguMzMsMzYuMjMsNDgsMzZabS04LjI1LTcuODJjMCwuNS0uMzEuOTEtLjY4LjlzLS42Ni0uNDItLjY1LS45Mi4zMS0uOTEuNjgtLjlTMzkuNzIsMjcuNjgsMzkuNzEsMjguMThabS0xLjY4LTZjLjcxLS4xMiwxLjA2LjYyLDEuMzIsMS44NWEzLjY0LDMuNjQsMCwwLDEtLjA1LDIsNC4xNCw0LjE0LDAsMCwwLTEuMDYsMCw0LjEzLDQuMTMsMCwwLDEtLjY4LTEuNjRDMzcuMjksMjMuMjMsMzcuMzEsMjIuMzQsMzgsMjIuMjNabS0yLjQsNi41N2EuODIuODIsMCwwLDEsMS4xMS0uMTljLjQ1LjIyLjY5LjY3LjUzLDFhLjgyLjgyLDAsMCwxLTEuMTEuMTlDMzUuNywyOS41OCwzNS40NywyOS4xMywzNS42MywyOC44Wm0tMi44LS4zN2MtLjA3LjExLS4yMy4wOS0uNTcuMDZhNC4yNCw0LjI0LDAsMCwwLTIuMTQuMjIsMiwyLDAsMCwxLS40OS4xNC4xNi4xNiwwLDAsMS0uMTEsMCwuMTUuMTUsMCwwLDEtLjA1LS4xMi44MS44MSwwLDAsMSwuMzItLjUxLDIuNDEsMi40MSwwLDAsMSwxLjI3LS41MywxLjk0LDEuOTQsMCwwLDEsMS43NS41N0EuMTkuMTksMCwwLDEsMzIuODMsMjguNDNabS01LjExLTEuMjZjLS4xMiwwLS4xNy0uMDctLjE5LS4xNHMuMjgtLjU2LjYyLS44MWEzLjYsMy42LDAsMCwxLDMuNTEtLjQyQTMsMywwLDAsMSwzMywyNi44N2MuMTIuMi4xNS4zNS4wNy40NHMtLjQ0LDAtLjk1LS4yNGE0LjE4LDQuMTgsMCwwLDAtMi0uNDNBMjEuODUsMjEuODUsMCwwLDAsMjcuNzEsMjcuMTdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzUuNSwxMy4yOWMuMSwwLC4xNi0uMTUuMDctLjJhMTEsMTEsMCwwLDAtNC42OS0xLjIzLjA5LjA5LDAsMCwxLS4wNy0uMTQsNC43OCw0Ljc4LDAsMCwxLC44OC0uODkuMDkuMDksMCwwLDAtLjA2LS4xNiwxMi40NiwxMi40NiwwLDAsMC01LjYxLDIsLjA5LjA5LDAsMCwxLS4xMy0uMDksNi4xNiw2LjE2LDAsMCwxLC41OS0xLjQ1LjA4LjA4LDAsMCwwLS4xMS0uMTFBMjIuNzksMjIuNzksMCwwLDAsMjAsMTYuMjRhLjA5LjA5LDAsMCwwLC4xMi4xM0ExOS41MywxOS41MywwLDAsMSwyNywxMy4zMiwxOS4xLDE5LjEsMCwwLDEsMzUuNSwxMy4yOVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4zNCw2LjQyUzI2LjIzLDQsMjUuNiwzLjhDMjEuNjksMi43NCwxMy4yNCw4LjU3LDcuODQsMTYuMjcsNS42NiwxOS4zOSwyLjUzLDI0LjksNCwyNy43NGExMS40MywxMS40MywwLDAsMCwxLjc5LDEuNzJBNi42NSw2LjY1LDAsMCwxLDEwLDI2Ljc4LDM0LjIxLDM0LjIxLDAsMCwxLDIwLjgsMTEuNjIsNTUuMDksNTUuMDksMCwwLDEsMjguMzQsNi40MloiLz48L2c+PC9nPjwvc3ZnPg=='
);

// Rename the auto-generated first submenu item to "Form Settings".
add_submenu_page(
'mailchimp_sf_options',
esc_html__( 'Form Settings', 'mailchimp' ),
esc_html__( 'Form Settings', 'mailchimp' ),
MCSF_CAP_THRESHOLD,
'mailchimp_sf_options',
array( $this, 'settings_page' )
);

add_submenu_page(
'admin.php',
esc_html__( 'Create Mailchimp Account', 'mailchimp' ),
Expand Down
Loading
Loading