Initial commit: ATT Consent plugin v1.0.0

Google Consent Mode v2 cookie consent plugin with session attribution
preservation, custom script management, and gtag.js/GTM support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 05:45:42 +00:00
commit 6bf9f553de
19 changed files with 2726 additions and 0 deletions

127
admin/css/admin.css Normal file
View File

@@ -0,0 +1,127 @@
/* ATT Consent Admin Styles */
.att-cc-admin-wrap .nav-tab-wrapper {
margin-bottom: 20px;
}
.att-cc-tab-content {
background: #fff;
border: 1px solid #ccd0d4;
border-top: none;
padding: 20px;
}
/* Scripts table */
#att-cc-scripts-table .column-name { width: 25%; }
#att-cc-scripts-table .column-category { width: 15%; }
#att-cc-scripts-table .column-placement { width: 12%; }
#att-cc-scripts-table .column-priority { width: 10%; }
#att-cc-scripts-table .column-status { width: 12%; }
#att-cc-scripts-table .column-actions { width: 20%; }
.att-cc-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 12px;
font-weight: 600;
color: #fff;
}
.att-cc-badge--functional { background: #2196F3; }
.att-cc-badge--analytics { background: #FF9800; }
.att-cc-badge--marketing { background: #9C27B0; }
.att-cc-status {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 12px;
}
.att-cc-status--active {
background: #e7f5e7;
color: #2e7d32;
}
.att-cc-status--inactive {
background: #f5e7e7;
color: #c62828;
}
/* Admin modal */
.att-cc-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100100;
display: flex;
align-items: center;
justify-content: center;
}
.att-cc-modal__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
}
.att-cc-modal__content {
position: relative;
background: #fff;
border-radius: 4px;
padding: 24px;
max-width: 700px;
width: 90%;
max-height: 85vh;
overflow-y: auto;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
.att-cc-modal__content h2 {
margin-top: 0;
}
.att-cc-modal__actions {
padding-top: 16px;
border-top: 1px solid #ddd;
display: flex;
gap: 8px;
}
/* Code textarea */
textarea.code {
font-family: Consolas, Monaco, 'Courier New', monospace;
font-size: 13px;
tab-size: 4;
}
/* Color picker spacing */
.att-cc-admin-wrap .wp-picker-container {
display: inline-block;
}
/* Feedback messages */
.att-cc-feedback {
padding: 8px 12px;
margin: 10px 0;
border-radius: 3px;
display: none;
}
.att-cc-feedback--success {
background: #e7f5e7;
border: 1px solid #2e7d32;
color: #2e7d32;
}
.att-cc-feedback--error {
background: #f5e7e7;
border: 1px solid #c62828;
color: #c62828;
}

166
admin/js/admin.js Normal file
View File

@@ -0,0 +1,166 @@
/* global jQuery, attCCAdmin */
(function($) {
'use strict';
$(function() {
// Initialize color pickers.
$('.att-cc-color-picker').wpColorPicker();
// Toggle gtag/GTM fields based on tracking mode.
var $trackingMode = $('#tracking_mode');
function toggleTrackingFields() {
var mode = $trackingMode.val();
$('.att-cc-gtag-row').toggle(mode === 'gtag');
$('.att-cc-gtm-row').toggle(mode === 'gtm');
}
if ($trackingMode.length) {
toggleTrackingFields();
$trackingMode.on('change', toggleTrackingFields);
}
// --- Custom Scripts CRUD ---
var $modal = $('#att-cc-script-modal');
var $form = $('#att-cc-script-form');
var $title = $('#att-cc-script-modal-title');
var $scriptId = $('#att-cc-script-id');
// Open modal for new script.
$('#att-cc-add-script').on('click', function() {
resetForm();
$title.text('Add Script');
$modal.show();
});
// Close modal.
$('.att-cc-close-modal, .att-cc-modal__overlay').on('click', function() {
$modal.hide();
});
// Escape key closes modal.
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && $modal.is(':visible')) {
$modal.hide();
}
});
// Edit script.
$(document).on('click', '.att-cc-edit-script', function() {
var id = $(this).data('id');
$.post(attCCAdmin.ajaxUrl, {
action: 'att_cc_get_script',
nonce: attCCAdmin.nonce,
script_id: id,
}, function(response) {
if (response.success) {
var s = response.data;
$scriptId.val(s.id);
$('#att-cc-script-name').val(s.name);
$('#att-cc-script-category').val(s.category);
$('#att-cc-script-placement').val(s.placement);
$('#att-cc-script-priority').val(s.priority);
$('#att-cc-script-status').val(s.status);
$('#att-cc-script-snippet').val(s.snippet);
$title.text('Edit Script');
$modal.show();
}
});
});
// Delete script.
$(document).on('click', '.att-cc-delete-script', function() {
if (!confirm(attCCAdmin.strings.confirmDelete)) {
return;
}
var id = $(this).data('id');
$.post(attCCAdmin.ajaxUrl, {
action: 'att_cc_delete_script',
nonce: attCCAdmin.nonce,
script_id: id,
}, function(response) {
if (response.success) {
refreshScriptsTable(response.data.scripts);
} else {
alert(attCCAdmin.strings.error);
}
});
});
// Save script (form submit).
$form.on('submit', function(e) {
e.preventDefault();
var data = {
action: 'att_cc_save_script',
nonce: attCCAdmin.nonce,
script_id: $scriptId.val(),
name: $('#att-cc-script-name').val(),
snippet: $('#att-cc-script-snippet').val(),
category: $('#att-cc-script-category').val(),
placement: $('#att-cc-script-placement').val(),
status: $('#att-cc-script-status').val(),
priority: $('#att-cc-script-priority').val(),
};
$.post(attCCAdmin.ajaxUrl, data, function(response) {
if (response.success) {
$modal.hide();
refreshScriptsTable(response.data.scripts);
} else {
alert(attCCAdmin.strings.error);
}
});
});
function resetForm() {
$scriptId.val('');
$('#att-cc-script-name').val('');
$('#att-cc-script-category').val('analytics');
$('#att-cc-script-placement').val('head');
$('#att-cc-script-priority').val('10');
$('#att-cc-script-status').val('active');
$('#att-cc-script-snippet').val('');
}
function refreshScriptsTable(scripts) {
var $tbody = $('#att-cc-scripts-list');
$tbody.empty();
if (!scripts || scripts.length === 0) {
$tbody.append('<tr class="att-cc-no-scripts"><td colspan="6">No custom scripts added yet.</td></tr>');
return;
}
var categoryColors = {
functional: 'functional',
analytics: 'analytics',
marketing: 'marketing',
};
scripts.forEach(function(s) {
var row = '<tr data-id="' + s.id + '">' +
'<td class="column-name">' + escapeHtml(s.name) + '</td>' +
'<td class="column-category"><span class="att-cc-badge att-cc-badge--' + s.category + '">' + capitalize(s.category) + '</span></td>' +
'<td class="column-placement">' + capitalize(s.placement) + '</td>' +
'<td class="column-priority">' + s.priority + '</td>' +
'<td class="column-status"><span class="att-cc-status att-cc-status--' + s.status + '">' + capitalize(s.status) + '</span></td>' +
'<td class="column-actions">' +
'<button type="button" class="button button-small att-cc-edit-script" data-id="' + s.id + '">Edit</button> ' +
'<button type="button" class="button button-small button-link-delete att-cc-delete-script" data-id="' + s.id + '">Delete</button>' +
'</td>' +
'</tr>';
$tbody.append(row);
});
}
function escapeHtml(text) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
});
})(jQuery);

View File

@@ -0,0 +1,89 @@
<?php
/**
* Advanced settings tab.
*
* @package ATT_Consent
* @var array $settings Current settings.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<?php wp_nonce_field( 'att_cc_save_settings' ); ?>
<input type="hidden" name="action" value="att_cc_save_settings">
<input type="hidden" name="att_cc_tab" value="advanced">
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'URL Passthrough', 'att-consent' ); ?></th>
<td>
<label>
<input type="checkbox" name="url_passthrough" value="1" <?php checked( $settings['url_passthrough'] ); ?>>
<?php esc_html_e( 'Enable URL passthrough', 'att-consent' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Passes ad click information (gclid, dclid) through URL parameters when navigating between pages, even before consent is granted. Recommended for better conversion attribution.', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Ads Data Redaction', 'att-consent' ); ?></th>
<td>
<label>
<input type="checkbox" name="ads_data_redaction" value="1" <?php checked( $settings['ads_data_redaction'] ); ?>>
<?php esc_html_e( 'Enable ads data redaction', 'att-consent' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'When ad_storage is denied, redacts ad click identifiers sent in network requests. Provides additional privacy protection.', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wait_for_update"><?php esc_html_e( 'Wait for Update (ms)', 'att-consent' ); ?></label>
</th>
<td>
<input type="number" name="wait_for_update" id="wait_for_update"
value="<?php echo esc_attr( $settings['wait_for_update'] ); ?>"
class="small-text" min="100" max="10000" step="100">
<p class="description">
<?php esc_html_e( 'How long Google tags wait for a consent update before firing with default (denied) state. 500ms is the recommended default. Only applies on first visit.', 'att-consent' ); ?>
</p>
</td>
</tr>
</table>
<h2><?php esc_html_e( 'Google Consent Mode v2 Signal Reference', 'att-consent' ); ?></h2>
<table class="widefat fixed" style="max-width: 700px;">
<thead>
<tr>
<th><?php esc_html_e( 'Consent Category', 'att-consent' ); ?></th>
<th><?php esc_html_e( 'Google Consent Signals', 'att-consent' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong><?php esc_html_e( 'Necessary', 'att-consent' ); ?></strong></td>
<td><code>security_storage</code> <?php esc_html_e( '(always granted)', 'att-consent' ); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Functional', 'att-consent' ); ?></strong></td>
<td><code>functionality_storage</code>, <code>personalization_storage</code></td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Analytics', 'att-consent' ); ?></strong></td>
<td><code>analytics_storage</code></td>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Marketing', 'att-consent' ); ?></strong></td>
<td><code>ad_storage</code>, <code>ad_user_data</code>, <code>ad_personalization</code></td>
</tr>
</tbody>
</table>
<?php submit_button(); ?>
</form>

View File

@@ -0,0 +1,118 @@
<?php
/**
* Appearance settings tab.
*
* @package ATT_Consent
* @var array $settings Current settings.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<?php wp_nonce_field( 'att_cc_save_settings' ); ?>
<input type="hidden" name="action" value="att_cc_save_settings">
<input type="hidden" name="att_cc_tab" value="appearance">
<h2><?php esc_html_e( 'Banner Text', 'att-consent' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row">
<label for="banner_heading"><?php esc_html_e( 'Heading', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="banner_heading" id="banner_heading"
value="<?php echo esc_attr( $settings['banner_heading'] ); ?>"
class="large-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="banner_message"><?php esc_html_e( 'Message', 'att-consent' ); ?></label>
</th>
<td>
<textarea name="banner_message" id="banner_message" rows="4"
class="large-text"><?php echo esc_textarea( $settings['banner_message'] ); ?></textarea>
<p class="description"><?php esc_html_e( 'Basic HTML is allowed (links, bold, italic).', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="btn_accept_label"><?php esc_html_e( 'Accept Button Label', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="btn_accept_label" id="btn_accept_label"
value="<?php echo esc_attr( $settings['btn_accept_label'] ); ?>" class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="btn_reject_label"><?php esc_html_e( 'Reject Button Label', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="btn_reject_label" id="btn_reject_label"
value="<?php echo esc_attr( $settings['btn_reject_label'] ); ?>" class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="btn_preferences_label"><?php esc_html_e( 'Preferences Button Label', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="btn_preferences_label" id="btn_preferences_label"
value="<?php echo esc_attr( $settings['btn_preferences_label'] ); ?>" class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="btn_save_label"><?php esc_html_e( 'Save Preferences Label', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="btn_save_label" id="btn_save_label"
value="<?php echo esc_attr( $settings['btn_save_label'] ); ?>" class="regular-text">
</td>
</tr>
</table>
<h2><?php esc_html_e( 'Colours', 'att-consent' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Banner Background', 'att-consent' ); ?></th>
<td><input type="text" name="banner_bg_color" value="<?php echo esc_attr( $settings['banner_bg_color'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Banner Text', 'att-consent' ); ?></th>
<td><input type="text" name="banner_text_color" value="<?php echo esc_attr( $settings['banner_text_color'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Accept Button Background', 'att-consent' ); ?></th>
<td><input type="text" name="btn_accept_bg" value="<?php echo esc_attr( $settings['btn_accept_bg'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Accept Button Text', 'att-consent' ); ?></th>
<td><input type="text" name="btn_accept_text" value="<?php echo esc_attr( $settings['btn_accept_text'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Reject Button Background', 'att-consent' ); ?></th>
<td><input type="text" name="btn_reject_bg" value="<?php echo esc_attr( $settings['btn_reject_bg'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Reject Button Text', 'att-consent' ); ?></th>
<td><input type="text" name="btn_reject_text" value="<?php echo esc_attr( $settings['btn_reject_text'] ); ?>" class="att-cc-color-picker"></td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Preferences Button Background', 'att-consent' ); ?></th>
<td>
<input type="text" name="btn_preferences_bg" value="<?php echo esc_attr( $settings['btn_preferences_bg'] ); ?>" class="att-cc-color-picker">
<p class="description"><?php esc_html_e( 'Use "transparent" for an outline-style button.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Preferences Button Text', 'att-consent' ); ?></th>
<td><input type="text" name="btn_preferences_text" value="<?php echo esc_attr( $settings['btn_preferences_text'] ); ?>" class="att-cc-color-picker"></td>
</tr>
</table>
<?php submit_button(); ?>
</form>

View File

@@ -0,0 +1,64 @@
<?php
/**
* Categories settings tab.
*
* @package ATT_Consent
* @var array $settings Current settings.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<?php wp_nonce_field( 'att_cc_save_settings' ); ?>
<input type="hidden" name="action" value="att_cc_save_settings">
<input type="hidden" name="att_cc_tab" value="categories">
<p><?php esc_html_e( 'Customise the descriptions shown to visitors for each cookie category in the preferences modal.', 'att-consent' ); ?></p>
<table class="form-table">
<tr>
<th scope="row">
<label for="cat_necessary_desc"><?php esc_html_e( 'Necessary', 'att-consent' ); ?></label>
</th>
<td>
<textarea name="cat_necessary_desc" id="cat_necessary_desc" rows="3"
class="large-text"><?php echo esc_textarea( $settings['cat_necessary_desc'] ); ?></textarea>
<p class="description"><?php esc_html_e( 'Always enabled. Maps to: security_storage.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="cat_functional_desc"><?php esc_html_e( 'Functional', 'att-consent' ); ?></label>
</th>
<td>
<textarea name="cat_functional_desc" id="cat_functional_desc" rows="3"
class="large-text"><?php echo esc_textarea( $settings['cat_functional_desc'] ); ?></textarea>
<p class="description"><?php esc_html_e( 'Maps to: functionality_storage, personalization_storage.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="cat_analytics_desc"><?php esc_html_e( 'Analytics', 'att-consent' ); ?></label>
</th>
<td>
<textarea name="cat_analytics_desc" id="cat_analytics_desc" rows="3"
class="large-text"><?php echo esc_textarea( $settings['cat_analytics_desc'] ); ?></textarea>
<p class="description"><?php esc_html_e( 'Maps to: analytics_storage.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="cat_marketing_desc"><?php esc_html_e( 'Marketing', 'att-consent' ); ?></label>
</th>
<td>
<textarea name="cat_marketing_desc" id="cat_marketing_desc" rows="3"
class="large-text"><?php echo esc_textarea( $settings['cat_marketing_desc'] ); ?></textarea>
<p class="description"><?php esc_html_e( 'Maps to: ad_storage, ad_user_data, ad_personalization.', 'att-consent' ); ?></p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>

View File

@@ -0,0 +1,120 @@
<?php
/**
* General settings tab.
*
* @package ATT_Consent
* @var array $settings Current settings.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<?php wp_nonce_field( 'att_cc_save_settings' ); ?>
<input type="hidden" name="action" value="att_cc_save_settings">
<input type="hidden" name="att_cc_tab" value="general">
<table class="form-table">
<tr>
<th scope="row">
<label for="tracking_mode"><?php esc_html_e( 'Tracking Mode', 'att-consent' ); ?></label>
</th>
<td>
<select name="tracking_mode" id="tracking_mode">
<option value="gtag" <?php selected( $settings['tracking_mode'], 'gtag' ); ?>>
<?php esc_html_e( 'Google Analytics (gtag.js)', 'att-consent' ); ?>
</option>
<option value="gtm" <?php selected( $settings['tracking_mode'], 'gtm' ); ?>>
<?php esc_html_e( 'Google Tag Manager', 'att-consent' ); ?>
</option>
</select>
<p class="description">
<?php esc_html_e( 'Choose whether to inject gtag.js directly or use a GTM container.', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr class="att-cc-gtag-row">
<th scope="row">
<label for="ga4_measurement_id"><?php esc_html_e( 'GA4 Measurement ID', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="ga4_measurement_id" id="ga4_measurement_id"
value="<?php echo esc_attr( $settings['ga4_measurement_id'] ); ?>"
class="regular-text" placeholder="G-XXXXXXXXXX">
<p class="description">
<?php esc_html_e( 'Your GA4 Measurement ID (starts with G-).', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr class="att-cc-gtm-row">
<th scope="row">
<label for="gtm_container_id"><?php esc_html_e( 'GTM Container ID', 'att-consent' ); ?></label>
</th>
<td>
<input type="text" name="gtm_container_id" id="gtm_container_id"
value="<?php echo esc_attr( $settings['gtm_container_id'] ); ?>"
class="regular-text" placeholder="GTM-XXXXXXX">
<p class="description">
<?php esc_html_e( 'Your Google Tag Manager Container ID (starts with GTM-).', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="consent_mode"><?php esc_html_e( 'Consent Mode', 'att-consent' ); ?></label>
</th>
<td>
<select name="consent_mode" id="consent_mode">
<option value="advanced" <?php selected( $settings['consent_mode'], 'advanced' ); ?>>
<?php esc_html_e( 'Advanced (recommended)', 'att-consent' ); ?>
</option>
<option value="basic" <?php selected( $settings['consent_mode'], 'basic' ); ?>>
<?php esc_html_e( 'Basic', 'att-consent' ); ?>
</option>
</select>
<p class="description">
<?php esc_html_e( 'Advanced: Tags load before consent, sending cookieless pings for better modelling. Basic: No tags load until consent is given.', 'att-consent' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="banner_position"><?php esc_html_e( 'Banner Position', 'att-consent' ); ?></label>
</th>
<td>
<select name="banner_position" id="banner_position">
<option value="bottom" <?php selected( $settings['banner_position'], 'bottom' ); ?>>
<?php esc_html_e( 'Bottom Bar', 'att-consent' ); ?>
</option>
<option value="top" <?php selected( $settings['banner_position'], 'top' ); ?>>
<?php esc_html_e( 'Top Bar', 'att-consent' ); ?>
</option>
<option value="center" <?php selected( $settings['banner_position'], 'center' ); ?>>
<?php esc_html_e( 'Centre Modal', 'att-consent' ); ?>
</option>
</select>
</td>
</tr>
<tr>
<th scope="row">
<label for="consent_expiry"><?php esc_html_e( 'Consent Expiry (days)', 'att-consent' ); ?></label>
</th>
<td>
<input type="number" name="consent_expiry" id="consent_expiry"
value="<?php echo esc_attr( $settings['consent_expiry'] ); ?>"
class="small-text" min="1" max="730">
<p class="description">
<?php esc_html_e( 'How long the consent cookie lasts before the user is asked again.', 'att-consent' ); ?>
</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>

View File

@@ -0,0 +1,133 @@
<?php
/**
* Custom Scripts tab.
*
* @package ATT_Consent
* @var array $settings Current settings.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$scripts = ATT_Consent_Scripts_Manager::get_all_scripts();
?>
<div class="att-cc-scripts-wrap">
<h2>
<?php esc_html_e( 'Custom Scripts', 'att-consent' ); ?>
<button type="button" class="page-title-action" id="att-cc-add-script">
<?php esc_html_e( 'Add New Script', 'att-consent' ); ?>
</button>
</h2>
<p><?php esc_html_e( 'Add custom JavaScript snippets that will only execute after the visitor consents to the relevant category. This is useful for conversion pixels, chat widgets, and other third-party scripts.', 'att-consent' ); ?></p>
<!-- Scripts list -->
<table class="wp-list-table widefat fixed striped" id="att-cc-scripts-table">
<thead>
<tr>
<th class="column-name"><?php esc_html_e( 'Name', 'att-consent' ); ?></th>
<th class="column-category"><?php esc_html_e( 'Category', 'att-consent' ); ?></th>
<th class="column-placement"><?php esc_html_e( 'Placement', 'att-consent' ); ?></th>
<th class="column-priority"><?php esc_html_e( 'Priority', 'att-consent' ); ?></th>
<th class="column-status"><?php esc_html_e( 'Status', 'att-consent' ); ?></th>
<th class="column-actions"><?php esc_html_e( 'Actions', 'att-consent' ); ?></th>
</tr>
</thead>
<tbody id="att-cc-scripts-list">
<?php if ( empty( $scripts ) ) : ?>
<tr class="att-cc-no-scripts">
<td colspan="6"><?php esc_html_e( 'No custom scripts added yet.', 'att-consent' ); ?></td>
</tr>
<?php else : ?>
<?php foreach ( $scripts as $script ) : ?>
<tr data-id="<?php echo esc_attr( $script['id'] ); ?>">
<td class="column-name"><?php echo esc_html( $script['name'] ); ?></td>
<td class="column-category"><span class="att-cc-badge att-cc-badge--<?php echo esc_attr( $script['category'] ); ?>"><?php echo esc_html( ucfirst( $script['category'] ) ); ?></span></td>
<td class="column-placement"><?php echo esc_html( ucfirst( $script['placement'] ) ); ?></td>
<td class="column-priority"><?php echo esc_html( $script['priority'] ); ?></td>
<td class="column-status">
<span class="att-cc-status att-cc-status--<?php echo esc_attr( $script['status'] ); ?>">
<?php echo esc_html( ucfirst( $script['status'] ) ); ?>
</span>
</td>
<td class="column-actions">
<button type="button" class="button button-small att-cc-edit-script" data-id="<?php echo esc_attr( $script['id'] ); ?>">
<?php esc_html_e( 'Edit', 'att-consent' ); ?>
</button>
<button type="button" class="button button-small button-link-delete att-cc-delete-script" data-id="<?php echo esc_attr( $script['id'] ); ?>">
<?php esc_html_e( 'Delete', 'att-consent' ); ?>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<!-- Add/Edit modal -->
<div id="att-cc-script-modal" class="att-cc-modal" style="display:none;">
<div class="att-cc-modal__overlay"></div>
<div class="att-cc-modal__content">
<h2 id="att-cc-script-modal-title"><?php esc_html_e( 'Add Script', 'att-consent' ); ?></h2>
<form id="att-cc-script-form">
<input type="hidden" name="script_id" id="att-cc-script-id" value="">
<table class="form-table">
<tr>
<th><label for="att-cc-script-name"><?php esc_html_e( 'Name', 'att-consent' ); ?></label></th>
<td><input type="text" id="att-cc-script-name" name="name" class="regular-text" required></td>
</tr>
<tr>
<th><label for="att-cc-script-category"><?php esc_html_e( 'Category', 'att-consent' ); ?></label></th>
<td>
<select id="att-cc-script-category" name="category">
<option value="functional"><?php esc_html_e( 'Functional', 'att-consent' ); ?></option>
<option value="analytics" selected><?php esc_html_e( 'Analytics', 'att-consent' ); ?></option>
<option value="marketing"><?php esc_html_e( 'Marketing', 'att-consent' ); ?></option>
</select>
<p class="description"><?php esc_html_e( 'The script will only execute after the visitor consents to this category.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th><label for="att-cc-script-placement"><?php esc_html_e( 'Placement', 'att-consent' ); ?></label></th>
<td>
<select id="att-cc-script-placement" name="placement">
<option value="head"><?php esc_html_e( 'Head', 'att-consent' ); ?></option>
<option value="footer"><?php esc_html_e( 'Footer', 'att-consent' ); ?></option>
</select>
</td>
</tr>
<tr>
<th><label for="att-cc-script-priority"><?php esc_html_e( 'Priority', 'att-consent' ); ?></label></th>
<td>
<input type="number" id="att-cc-script-priority" name="priority" value="10" min="1" max="100" class="small-text">
<p class="description"><?php esc_html_e( 'Lower numbers execute first.', 'att-consent' ); ?></p>
</td>
</tr>
<tr>
<th><label for="att-cc-script-status"><?php esc_html_e( 'Status', 'att-consent' ); ?></label></th>
<td>
<select id="att-cc-script-status" name="status">
<option value="active"><?php esc_html_e( 'Active', 'att-consent' ); ?></option>
<option value="inactive"><?php esc_html_e( 'Inactive', 'att-consent' ); ?></option>
</select>
</td>
</tr>
<tr>
<th><label for="att-cc-script-snippet"><?php esc_html_e( 'Script Code', 'att-consent' ); ?></label></th>
<td>
<textarea id="att-cc-script-snippet" name="snippet" rows="10" class="large-text code" placeholder="<script>&#10;// Your code here&#10;</script>"></textarea>
<p class="description"><?php esc_html_e( 'Include the full script tag(s). This code will be injected into the page after consent is given for the selected category.', 'att-consent' ); ?></p>
</td>
</tr>
</table>
<div class="att-cc-modal__actions">
<button type="submit" class="button button-primary"><?php esc_html_e( 'Save Script', 'att-consent' ); ?></button>
<button type="button" class="button att-cc-close-modal"><?php esc_html_e( 'Cancel', 'att-consent' ); ?></button>
</div>
</form>
</div>
</div>
</div>