文章目录[隐藏]
WordPress插件开发教程:实现多维度网站用户分群与精准推送
引言:为什么需要用户分群与精准推送?
在当今互联网时代,网站访问者不再满足于千篇一律的内容体验。根据Salesforce的研究,个性化内容可以将转化率提高20%。对于WordPress网站运营者而言,理解用户行为并提供定制化内容已成为提升用户参与度和转化率的关键策略。
传统的WordPress网站通常向所有访问者展示相同的内容,无论他们的兴趣、行为或背景如何。这种"一刀切"的方法已经无法满足现代用户的需求。通过开发自定义插件实现多维度用户分群与精准推送,我们可以:
- 提高用户参与度和页面停留时间
- 增加内容相关性和用户满意度
- 提升转化率和商业价值
- 收集有价值的用户行为数据
本教程将引导您从零开始开发一个功能完整的WordPress插件,实现多维度用户分群与精准推送功能,同时融入常用互联网小工具,增强网站互动性。
第一章:开发环境准备与插件基础框架
1.1 开发环境配置
在开始插件开发前,确保您已准备好以下环境:
- WordPress 5.0+ 本地或测试环境
- PHP 7.2+ 版本
- MySQL 5.6+ 或 MariaDB 10.0+
- 代码编辑器(推荐VS Code或PHPStorm)
- 浏览器开发者工具
1.2 创建插件基础结构
首先,在WordPress的wp-content/plugins/目录下创建新文件夹user-segmentation-tools,并创建以下基础文件:
user-segmentation-tools/
├── user-segmentation-tools.php # 主插件文件
├── includes/ # 包含核心功能文件
│ ├── class-user-segmenter.php # 用户分群核心类
│ ├── class-content-pusher.php # 内容推送类
│ ├── class-data-collector.php # 数据收集类
│ └── class-tools-integration.php # 小工具集成类
├── admin/ # 后台管理文件
│ ├── css/
│ ├── js/
│ └── views/
├── public/ # 前端文件
│ ├── css/
│ ├── js/
│ └── views/
├── assets/ # 静态资源
└── uninstall.php # 插件卸载脚本
1.3 主插件文件配置
编辑user-segmentation-tools.php,添加插件基本信息:
<?php
/**
* Plugin Name: 用户分群与精准推送工具
* Plugin URI: https://yourwebsite.com/
* Description: 实现多维度网站用户分群与精准推送功能,集成常用互联网小工具
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: user-segmentation-tools
* Domain Path: /languages
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('UST_VERSION', '1.0.0');
define('UST_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('UST_PLUGIN_URL', plugin_dir_url(__FILE__));
define('UST_PLUGIN_BASENAME', plugin_basename(__FILE__));
// 自动加载类文件
spl_autoload_register(function ($class_name) {
$prefix = 'UST_';
$base_dir = UST_PLUGIN_DIR . 'includes/';
$len = strlen($prefix);
if (strncmp($prefix, $class_name, $len) !== 0) {
return;
}
$relative_class = substr($class_name, $len);
$file = $base_dir . 'class-' . str_replace('_', '-', strtolower($relative_class)) . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化插件
function ust_init_plugin() {
// 检查WordPress版本
if (version_compare(get_bloginfo('version'), '5.0', '<')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>';
echo __('用户分群与精准推送工具需要WordPress 5.0或更高版本。', 'user-segmentation-tools');
echo '</p></div>';
});
return;
}
// 初始化核心类
$user_segmenter = new UST_User_Segmenter();
$content_pusher = new UST_Content_Pusher();
$data_collector = new UST_Data_Collector();
$tools_integration = new UST_Tools_Integration();
// 注册激活/停用钩子
register_activation_hook(__FILE__, ['UST_User_Segmenter', 'activate']);
register_deactivation_hook(__FILE__, ['UST_User_Segmenter', 'deactivate']);
// 加载文本域
load_plugin_textdomain('user-segmentation-tools', false, dirname(UST_PLUGIN_BASENAME) . '/languages');
}
add_action('plugins_loaded', 'ust_init_plugin');
第二章:用户数据收集与存储机制
2.1 设计用户数据表结构
为了实现多维度用户分群,我们需要收集和存储用户行为数据。在class-user-segmenter.php中创建数据库表:
class UST_User_Segmenter {
public static function activate() {
self::create_tables();
self::create_default_segments();
}
private static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name_users = $wpdb->prefix . 'ust_user_data';
$table_name_behavior = $wpdb->prefix . 'ust_user_behavior';
$table_name_segments = $wpdb->prefix . 'ust_user_segments';
// 用户数据表
$sql_users = "CREATE TABLE IF NOT EXISTS $table_name_users (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT(20) UNSIGNED DEFAULT NULL,
session_id VARCHAR(64) NOT NULL,
first_visit DATETIME NOT NULL,
last_visit DATETIME NOT NULL,
visit_count INT(11) DEFAULT 1,
device_type VARCHAR(50),
browser VARCHAR(100),
location VARCHAR(200),
referrer VARCHAR(500),
interests TEXT,
PRIMARY KEY (id),
UNIQUE KEY session_id (session_id),
KEY user_id (user_id),
KEY last_visit (last_visit)
) $charset_collate;";
// 用户行为表
$sql_behavior = "CREATE TABLE IF NOT EXISTS $table_name_behavior (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
user_data_id BIGINT(20) UNSIGNED NOT NULL,
behavior_type VARCHAR(50) NOT NULL,
behavior_value TEXT,
page_url VARCHAR(500),
timestamp DATETIME NOT NULL,
metadata TEXT,
PRIMARY KEY (id),
KEY user_data_id (user_data_id),
KEY behavior_type (behavior_type),
KEY timestamp (timestamp)
) $charset_collate;";
// 用户分群表
$sql_segments = "CREATE TABLE IF NOT EXISTS $table_name_segments (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
segment_name VARCHAR(100) NOT NULL,
segment_slug VARCHAR(100) NOT NULL,
segment_rules TEXT NOT NULL,
user_count INT(11) DEFAULT 0,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
is_active TINYINT(1) DEFAULT 1,
PRIMARY KEY (id),
UNIQUE KEY segment_slug (segment_slug)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_users);
dbDelta($sql_behavior);
dbDelta($sql_segments);
}
}
2.2 实现用户数据收集
创建class-data-collector.php,实现用户行为跟踪:
class UST_Data_Collector {
private $user_data_id;
private $session_id;
public function __construct() {
$this->init_session();
$this->track_user();
add_action('wp_footer', [$this, 'add_tracking_script']);
}
private function init_session() {
if (!session_id()) {
session_start();
}
if (!isset($_SESSION['ust_session_id'])) {
$_SESSION['ust_session_id'] = $this->generate_session_id();
}
$this->session_id = $_SESSION['ust_session_id'];
}
private function generate_session_id() {
return md5(uniqid(mt_rand(), true) . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);
}
private function track_user() {
global $wpdb;
// 获取用户信息
$user_id = is_user_logged_in() ? get_current_user_id() : null;
$current_time = current_time('mysql');
// 检查是否已存在该会话记录
$table_name = $wpdb->prefix . 'ust_user_data';
$existing = $wpdb->get_row($wpdb->prepare(
"SELECT id FROM $table_name WHERE session_id = %s",
$this->session_id
));
if ($existing) {
$this->user_data_id = $existing->id;
// 更新最后访问时间
$wpdb->update(
$table_name,
[
'last_visit' => $current_time,
'visit_count' => $wpdb->get_var($wpdb->prepare(
"SELECT visit_count + 1 FROM $table_name WHERE id = %d",
$this->user_data_id
))
],
['id' => $this->user_data_id]
);
} else {
// 收集设备信息
$device_info = $this->get_device_info();
$location = $this->get_user_location();
// 插入新用户记录
$wpdb->insert(
$table_name,
[
'user_id' => $user_id,
'session_id' => $this->session_id,
'first_visit' => $current_time,
'last_visit' => $current_time,
'device_type' => $device_info['device_type'],
'browser' => $device_info['browser'],
'location' => $location,
'referrer' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '直接访问'
]
);
$this->user_data_id = $wpdb->insert_id;
}
// 记录页面访问行为
$this->record_behavior('page_view', [
'page_title' => wp_get_document_title(),
'page_url' => home_url($_SERVER['REQUEST_URI'])
]);
}
private function get_device_info() {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
// 简单设备检测
$device_type = 'desktop';
if (preg_match('/(android|webos|iphone|ipad|ipod|blackberry|windows phone)/i', $user_agent)) {
$device_type = 'mobile';
} elseif (preg_match('/(tablet|ipad|playbook|silk)/i', $user_agent)) {
$device_type = 'tablet';
}
// 浏览器检测
$browser = '未知浏览器';
if (preg_match('/MSIE|Trident/i', $user_agent)) {
$browser = 'Internet Explorer';
} elseif (preg_match('/Firefox/i', $user_agent)) {
$browser = 'Firefox';
} elseif (preg_match('/Chrome/i', $user_agent)) {
$browser = 'Chrome';
} elseif (preg_match('/Safari/i', $user_agent)) {
$browser = 'Safari';
} elseif (preg_match('/Edge/i', $user_agent)) {
$browser = 'Edge';
}
return [
'device_type' => $device_type,
'browser' => $browser
];
}
private function get_user_location() {
// 简化版地理位置获取
// 实际应用中可使用IP地理位置API
$ip = $_SERVER['REMOTE_ADDR'];
// 如果是本地环境,返回模拟位置
if ($ip === '127.0.0.1' || $ip === '::1') {
return '本地环境';
}
// 这里可以集成IP地理位置API
// 例如使用ipapi.co或ipstack.com的API
return '未知位置';
}
public function record_behavior($type, $value = null, $metadata = []) {
global $wpdb;
if (!$this->user_data_id) {
return false;
}
$table_name = $wpdb->prefix . 'ust_user_behavior';
return $wpdb->insert(
$table_name,
[
'user_data_id' => $this->user_data_id,
'behavior_type' => $type,
'behavior_value' => is_array($value) ? json_encode($value) : $value,
'page_url' => home_url($_SERVER['REQUEST_URI']),
'timestamp' => current_time('mysql'),
'metadata' => json_encode($metadata)
]
);
}
public function add_tracking_script() {
?>
<script type="text/javascript">
(function() {
// 跟踪用户交互行为
document.addEventListener('DOMContentLoaded', function() {
// 跟踪链接点击
document.querySelectorAll('a').forEach(function(link) {
link.addEventListener('click', function(e) {
var linkData = {
href: this.href,
text: this.textContent.substring(0, 100),
class: this.className
};
// 发送AJAX请求记录行为
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=ust_track_behavior&type=link_click&value=' + encodeURIComponent(JSON.stringify(linkData))
});
});
});
// 跟踪表单交互
document.querySelectorAll('form').forEach(function(form) {
form.addEventListener('submit', function(e) {
var formData = {
form_id: this.id || 'unnamed_form',
action: this.action
};
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=ust_track_behavior&type=form_submit&value=' + encodeURIComponent(JSON.stringify(formData))
});
});
});
// 跟踪滚动深度
var scrollTracked = false;
window.addEventListener('scroll', function() {
var scrollPercent = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100;
if (scrollPercent > 50 && !scrollTracked) {
scrollTracked = true;
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=ust_track_behavior&type=scroll_depth&value=50'
});
}
});
});
})();
</script>
<?php
}
}
第三章:多维度用户分群算法实现
3.1 设计分群规则引擎
在class-user-segmenter.php中扩展分群功能:
class UST_User_Segmenter {
private $segments = [];
public function __construct() {
$this->load_segments();
add_action('init', [$this, 'evaluate_user_segments']);
add_action('admin_menu', [$this, 'add_admin_menu']);
}
private function load_segments() {
global $wpdb;
$table_name = $wpdb->prefix . 'ust_user_segments';
$this->segments = $wpdb->get_results(
"SELECT * FROM $table_name WHERE is_active = 1"
);
}
public function evaluate_user_segments() {
if (is_admin()) {
return;
}
$user_segments = $this->get_user_segments();
setcookie('ust_user_segments', json_encode($user_segments), time() + 86400 * 30, '/');
$_SESSION['ust_user_segments'] = $user_segments;
}
private function get_user_segments() {
global $wpdb;
$user_segments = [];
$session_id = isset($_SESSION['ust_session_id']) ? $_SESSION['ust_session_id'] : '';
if (empty($session_id)) {
return $user_segments;
}
// 获取当前用户数据ID
$user_data_table = $wpdb->prefix . 'ust_user_data';
$user_data = $wpdb->get_row($wpdb->prepare(
"SELECT id, user_id, visit_count, device_type, location FROM $user_data_table WHERE session_id = %s",
$session_id
));
if (!$user_data) {
return $user_segments;
}
// 获取用户行为数据
$behavior_table = $wpdb->prefix . 'ust_user_behavior';
get_results($wpdb->prepare(
"SELECT behavior_type, COUNT(*) as count, MAX(timestamp) as last_time
FROM $behavior_table
WHERE user_data_id = %d
GROUP BY behavior_type",
$user_data->id
));
$behavior_summary = [];
foreach ($user_behaviors as $behavior) {
$behavior_summary[$behavior->behavior_type] = [
'count' => $behavior->count,
'last_time' => $behavior->last_time
];
}
// 评估每个分群规则
foreach ($this->segments as $segment) {
$rules = json_decode($segment->segment_rules, true);
if ($this->evaluate_rules($rules, $user_data, $behavior_summary)) {
$user_segments[] = $segment->segment_slug;
// 记录用户分群关系
$this->record_user_segment($user_data->id, $segment->id);
}
}
return $user_segments;
}
private function evaluate_rules($rules, $user_data, $behavior_summary) {
foreach ($rules as $rule_group) {
$group_result = true;
foreach ($rule_group as $rule) {
$rule_result = $this->evaluate_single_rule($rule, $user_data, $behavior_summary);
if (!$rule_result) {
$group_result = false;
break;
}
}
if ($group_result) {
return true;
}
}
return false;
}
private function evaluate_single_rule($rule, $user_data, $behavior_summary) {
$field = $rule['field'];
$operator = $rule['operator'];
$value = $rule['value'];
switch ($field) {
case 'visit_count':
$actual_value = $user_data->visit_count;
return $this->compare_values($actual_value, $operator, $value);
case 'device_type':
$actual_value = $user_data->device_type;
return $this->compare_strings($actual_value, $operator, $value);
case 'user_role':
$actual_value = $user_data->user_id ? $this->get_user_role($user_data->user_id) : 'guest';
return $this->compare_strings($actual_value, $operator, $value);
case 'behavior_count':
$behavior_type = $rule['behavior_type'] ?? 'page_view';
$actual_value = isset($behavior_summary[$behavior_type]) ? $behavior_summary[$behavior_type]['count'] : 0;
return $this->compare_values($actual_value, $operator, $value);
case 'last_visit_days':
$last_visit = strtotime($user_data->last_visit);
$days_diff = floor((time() - $last_visit) / (60 * 60 * 24));
return $this->compare_values($days_diff, $operator, $value);
case 'location':
$actual_value = $user_data->location;
return $this->compare_strings($actual_value, $operator, $value);
default:
return false;
}
}
private function compare_values($actual, $operator, $expected) {
switch ($operator) {
case 'equals': return $actual == $expected;
case 'not_equals': return $actual != $expected;
case 'greater_than': return $actual > $expected;
case 'less_than': return $actual < $expected;
case 'greater_than_equals': return $actual >= $expected;
case 'less_than_equals': return $actual <= $expected;
default: return false;
}
}
private function compare_strings($actual, $operator, $expected) {
switch ($operator) {
case 'equals': return strtolower($actual) == strtolower($expected);
case 'not_equals': return strtolower($actual) != strtolower($expected);
case 'contains': return stripos($actual, $expected) !== false;
case 'not_contains': return stripos($actual, $expected) === false;
case 'starts_with': return stripos($actual, $expected) === 0;
case 'ends_with':
$expected_length = strlen($expected);
return substr_compare($actual, $expected, -$expected_length, $expected_length, true) === 0;
default: return false;
}
}
private function get_user_role($user_id) {
$user = get_userdata($user_id);
if ($user && !empty($user->roles)) {
return $user->roles[0];
}
return 'guest';
}
private function record_user_segment($user_data_id, $segment_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'ust_user_segment_relationships';
// 检查是否已存在关系
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table_name
WHERE user_data_id = %d AND segment_id = %d",
$user_data_id, $segment_id
));
if (!$existing) {
$wpdb->insert(
$table_name,
[
'user_data_id' => $user_data_id,
'segment_id' => $segment_id,
'assigned_at' => current_time('mysql')
]
);
}
}
public function add_admin_menu() {
add_menu_page(
'用户分群管理',
'用户分群',
'manage_options',
'user-segmentation',
[$this, 'render_admin_page'],
'dashicons-groups',
30
);
add_submenu_page(
'user-segmentation',
'分群规则管理',
'分群规则',
'manage_options',
'user-segmentation-rules',
[$this, 'render_rules_page']
);
add_submenu_page(
'user-segmentation',
'用户行为分析',
'行为分析',
'manage_options',
'user-segmentation-analytics',
[$this, 'render_analytics_page']
);
}
public function render_admin_page() {
include UST_PLUGIN_DIR . 'admin/views/admin-main.php';
}
public function render_rules_page() {
include UST_PLUGIN_DIR . 'admin/views/rules-management.php';
}
public function render_analytics_page() {
include UST_PLUGIN_DIR . 'admin/views/analytics-dashboard.php';
}
}
## 第四章:精准内容推送系统
### 4.1 内容推送引擎设计
创建`class-content-pusher.php`:
class UST_Content_Pusher {
private $push_rules = [];
public function __construct() {
$this->load_push_rules();
add_filter('the_content', [$this, 'inject_targeted_content']);
add_action('wp_footer', [$this, 'inject_floating_widgets']);
add_action('admin_menu', [$this, 'add_push_rules_menu']);
}
private function load_push_rules() {
global $wpdb;
$table_name = $wpdb->prefix . 'ust_push_rules';
$this->push_rules = $wpdb->get_results(
"SELECT * FROM $table_name WHERE is_active = 1 ORDER BY priority DESC"
);
}
public function inject_targeted_content($content) {
if (is_admin() || !is_singular()) {
return $content;
}
$user_segments = $this->get_current_user_segments();
$post_id = get_the_ID();
$post_type = get_post_type();
foreach ($this->push_rules as $rule) {
if ($this->should_apply_rule($rule, $user_segments, $post_id, $post_type)) {
$content = $this->apply_push_rule($content, $rule);
}
}
return $content;
}
private function should_apply_rule($rule, $user_segments, $post_id, $post_type) {
$rule_data = json_decode($rule->rule_conditions, true);
// 检查目标分群
if (!empty($rule_data['target_segments'])) {
$intersection = array_intersect($user_segments, $rule_data['target_segments']);
if (empty($intersection)) {
return false;
}
}
// 检查内容类型
if (!empty($rule_data['post_types']) && !in_array($post_type, $rule_data['post_types'])) {
return false;
}
// 检查特定文章/页面
if (!empty($rule_data['specific_posts']) && !in_array($post_id, $rule_data['specific_posts'])) {
return false;
}
// 检查分类条件
if (!empty($rule_data['categories'])) {
$post_categories = wp_get_post_categories($post_id, ['fields' => 'ids']);
$intersection = array_intersect($post_categories, $rule_data['categories']);
if (empty($intersection)) {
return false;
}
}
// 检查标签条件
if (!empty($rule_data['tags'])) {
$post_tags = wp_get_post_tags($post_id, ['fields' => 'ids']);
$intersection = array_intersect($post_tags, $rule_data['tags']);
if (empty($intersection)) {
return false;
}
}
// 检查显示频率限制
if ($rule->display_limit > 0) {
$display_count = $this->get_rule_display_count($rule->id);
if ($display_count >= $rule->display_limit) {
return false;
}
}
return true;
}
private function apply_push_rule($content, $rule) {
$rule_data = json_decode($rule->rule_conditions, true);
$push_content = $this->get_push_content($rule->content_type, $rule->content_value);
if (!$push_content) {
return $content;
}
// 记录显示次数
$this->record_rule_display($rule->id);
// 根据位置插入内容
switch ($rule_data['position']) {
case 'before_content':
return $push_content . $content;
case 'after_content':
return $content . $push_content;
case 'after_paragraph':
$paragraph_number = $rule_data['paragraph_number'] ?? 3;
return $this->insert_after_paragraph($content, $push_content, $paragraph_number);
case 'replace_content':
$selector = $rule_data['css_selector'] ?? '';
if ($selector) {
return $this->replace_by_selector($content, $push_content, $selector);
}
return $content;
default:
return $content;
}
}
private function get_push_content($type, $value) {
switch ($type) {
case 'custom_html':
return do_shortcode($value);
case 'shortcode':
return do_shortcode($value);
case 'post':
$post = get_post($value);
if ($post) {
return apply_filters('the_content', $post->post_content);
}
break;
case 'widget':
return $this->render_widget($value);
case 'call_to_action':
return $this->render_cta($value);
}
return '';
}
private function insert_after_paragraph($content, $insertion, $paragraph_number) {
$paragraphs = explode('</p>', $content);
if (count($paragraphs) >= $paragraph_number) {
$paragraphs[$paragraph_number - 1] .= $insertion;
return implode('</p>', $paragraphs);
}
return $content . $insertion;
}
public function inject_floating_widgets() {
if (is_admin()) {
return;
}
$user_segments = $this->get_current_user_segments();
foreach ($this->push_rules as $rule) {
$rule_data = json_decode($rule->rule_conditions, true);
if ($rule_data['display_type'] === 'floating' &&
$this->should_apply_rule($rule, $user_segments, get_the_ID(), get_post_type())) {
$this->render_floating_widget($rule);
}
}
}
private function render_floating_widget($rule) {
$content = $this->get_push_content($rule->content_type, $rule->content_value);
$rule_data = json_decode($rule->rule_conditions, true);
?>
<div class="ust-floating-widget"
data-position="<?php echo esc_attr($rule_data['float_position']); ?>"
data-rule-id="<?php echo esc_attr($rule->id); ?>">
<div class="ust-floating-content">
<?php echo $content; ?>
</div>
<button class="ust-close-widget" aria-label="关闭">×</button>
</div>
<style>
.ust-floating-widget {
position: fixed;
z-index: 999999;
max-width: 300px;
background: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
padding: 20px;
animation: ust-fade-in 0.3s ease;
}
.ust-floating-widget[data-position="bottom-right"] {
bottom: 20px;
right: 20px;
}
.ust-floating-widget[data-position="bottom-left"] {
bottom: 20px;
left: 20px;
}
.ust-close-widget {
position: absolute;
top: 5px;
right: 10px;
background: none;
border: none;
font-size: 20px;
cursor: pointer;
color: #666;
}
@keyframes ust-fade-in {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.ust-close-widget').forEach(function(button) {
button.addEventListener('click', function() {
var widget = this.closest('.ust-floating-widget');
widget.style.display = 'none';
// 记录关闭行为
var ruleId = widget.getAttribute('data-rule-id');
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=ust_track_widget_close&rule_id=' + ruleId
});
});
});
});
</script>
<?php
}
private function get_current_user_segments() {
if (isset($_SESSION['ust_user_segments'])) {
return $_SESSION['ust_user_segments'];
}
if (isset($_COOKIE['ust_user_segments'])) {
return json_decode(stripslashes($_COOKIE['ust_user_segments']), true);
}
return [];
}
}
## 第五章:常用互联网小工具集成
### 5.1 小工具管理器实现
创建`class-tools-integration.php`:
class UST_Tools_Integration {
private $available_tools = [];
public function __construct() {
$this->register_tools();
add_action('widgets_init', [$this, 'register_widgets']);
add_shortcode('ust_tool', [$this, 'render_tool_shortcode']);
add_action('wp_ajax_ust_tool_action', [$this, 'handle_tool_ajax']);
add_action('wp_ajax_nopriv_ust_tool_action', [$this, 'handle_tool_ajax']);
}
private function register_tools() {
$this->available_tools = [
'poll' => [
'name' => '投票工具',
'description' => '创建简单的投票调查',
'callback' => [$this, 'render_poll_tool'],
'settings' => [
'question' => ['type' => 'text', 'label' => '问题'],
'options' => ['type' => 'textarea', 'label' => '选项(每行一个)'],
'multiple' => ['type' => 'checkbox', 'label' => '允许多选']
]
],
'calculator' => [
'name' => '计算器工具',
'description' => '简单的计算器功能',
'callback' => [$this, 'render_calculator_tool'],
'settings' => [
'type' => [
'type' => 'select',
'label' => '计算器类型',
'options' => [
'basic' => '基础计算器',
'loan' => '贷款计算器',
'currency' => '货币换算器'
]
]
]
],
'countdown' => [
'name' => '倒计时工具',
'description' => '创建活动倒计时',
'callback' => [$this, 'render_countdown_tool'],
'settings' => [
'target_date' => ['type' => 'date', 'label' => '目标日期'],
'title' => ['type' => 'text', 'label' => '标题'],
'show_days' => ['type' => 'checkbox', 'label' => '显示天数', 'default' => true]
]
],
'social_share' => [
'name' => '社交分享工具',
'description' => '增强的社交分享按钮',
'callback' => [$this, 'render_social_share_tool'],
