feat: add rData (Umami) analytics to p2pwiki, p2pf blog and website

- p2pwiki AI: tracking script in web/index.html
- Static blog: nginx sub_filter injection
- WordPress blog: theme header.php + mu-plugin
- WordPress website: mu-plugin via docker-compose volume mount
- Replaces legacy Google Analytics UA-184755-2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-10 14:06:08 -07:00
parent 6e08b21978
commit 100bca5910
5 changed files with 399 additions and 0 deletions

View File

@ -0,0 +1,141 @@
<?php
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) !== false ) )
{
header( 'X-UA-Compatible: IE=edge,chrome=1' );
}
$fixed_header = get_option( 'fixed_header', 'Yes' );
if ( $fixed_header == 'No' )
{
$fixed_header = "";
}
else
{
$fixed_header = 'is-header-fixed';
}
?>
<!doctype html>
<html <?php language_attributes(); ?> class="<?php echo $fixed_header; ?>">
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<?php
$mobile_zoom = get_option( 'mobile_zoom', 'Yes' );
if ( $mobile_zoom == 'No' )
{
?>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<?php
}
else
{
?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php
}
?>
<title><?php wp_title( '|', true, 'right' ); ?></title>
<?php
wp_head();
?>
<script defer src="https://rdata.online/collect.js" data-website-id="1faf3e11-797c-4733-90c3-c7f11a2592c5"></script>
</head>
<body <?php body_class(); ?>>
<div id="page" class="hfeed site">
<header id="masthead" class="site-header" role="banner">
<h1 class="site-title">
<?php
$logo_type = get_option( 'logo_type', 'Text Logo' );
if ( $logo_type == 'Image Logo' )
{
$logo_image = get_option( 'logo_image', "" );
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
<img alt="<?php bloginfo( 'name' ); ?>" src="<?php echo $logo_image; ?>">
</a>
<?php
}
else
{
$select_text_logo = get_option( 'select_text_logo', 'WordPress Site Title' );
if ( $select_text_logo == 'Theme Site Title' )
{
$text_logo_out = stripcslashes( get_option( 'theme_site_title', "" ) );
}
else
{
$text_logo_out = get_bloginfo( 'name' );
}
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php echo $text_logo_out; ?></a>
<?php
}
?>
</h1>
<nav id="primary-navigation" class="site-navigation primary-navigation" role="navigation">
<a class="menu-toggle toggle-link"></a>
<div class="nav-menu">
<?php
wp_nav_menu( array( 'theme_location' => 'pixelwars_theme_menu_location_1',
'menu' => 'pixelwars_theme_menu_location_1',
'menu_id' => 'nav',
'menu_class' => 'menu-custom vs-nav',
'container' => false,
'depth' => 0,
'fallback_cb' => 'pixelwars_wp_page_menu2' ) );
?>
</div>
</nav>
<?php
$nav_menu_search = get_option( 'nav_menu_search', 'No' );
if ( $nav_menu_search != 'No' )
{
?>
<div class="search-container easing">
<a class="search-toggle toggle-link"></a>
<div class="search-box">
<form class="search-form" role="search" method="get" action="<?php echo esc_url( home_url( '/' ) ); ?>">
<label>
<span class="screen-reader-text"><?php echo __( 'Search for:', 'read' ); ?></span>
<input type="search" name="s" id="search-field" placeholder="<?php echo __( 'type and hit enter', 'read' ); ?> &#8230;">
</label>
<input type="submit" class="search-submit" value="<?php echo __( 'Search', 'read' ); ?>">
</form>
</div>
</div>
<?php
}
?>
<div class="social-container">
<a class="social-toggle toggle-link"></a>
<?php
if ( ! function_exists( 'dynamic_sidebar' ) || ! dynamic_sidebar( 'pixelwars_header_sidebar' ) ) :
endif;
?>
</div>
</header>

View File

@ -0,0 +1,190 @@
version: "3.8"
services:
db:
image: mariadb:10.11
container_name: p2p-db
restart: unless-stopped
command: --max-connections=300 --wait-timeout=300 --interactive-timeout=300
environment:
MYSQL_ROOT_PASSWORD: p2p_secure_root_2025
volumes:
- db_data:/var/lib/mysql
- ./init-db:/docker-entrypoint-initdb.d
networks:
- p2p-internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 30s
timeout: 10s
retries: 5
wiki:
image: mediawiki:1.41
container_name: p2p-wiki
restart: unless-stopped
environment:
- MEDIAWIKI_DB_HOST=db
- MEDIAWIKI_DB_NAME=p2p_wiki
- MEDIAWIKI_DB_USER=p2p_wiki
- MEDIAWIKI_DB_PASSWORD=wiki_secure_2025
volumes:
- wiki_data:/var/www/html/images
- ./wiki-config:/var/www/html/config
- ./robots-wiki.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-wiki.rule=Host(`wiki.p2pfoundation.net`)"
- "traefik.http.services.p2p-wiki.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
blog:
image: wordpress:6.4-php8.2-apache
container_name: p2p-blog
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: p2p_blog
WORDPRESS_DB_USER: p2p_blog
WORDPRESS_DB_PASSWORD: blog_secure_2025
volumes:
- blog_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./robots.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
- ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-blog.rule=Host(`blog.p2pfoundation.net`) || Host(`www.blog.p2pfoundation.net`)"
- "traefik.http.services.p2p-blog.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
bloggr:
image: wordpress:6.4-php8.2-apache
container_name: p2p-bloggr
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: p2p_bloggr
WORDPRESS_DB_USER: p2p_bloggr
WORDPRESS_DB_PASSWORD: bloggr_secure_2025
volumes:
- bloggr_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./robots.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
- ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-bloggr.rule=Host(`bloggr.p2pfoundation.net`)"
- "traefik.http.services.p2p-bloggr.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
blogfr:
image: wordpress:6.4-php8.2-apache
container_name: p2p-blogfr
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: p2p_blogfr
WORDPRESS_DB_USER: p2p_blogfr
WORDPRESS_DB_PASSWORD: blogfr_secure_2025
volumes:
- blogfr_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./robots.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
- ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-blogfr.rule=Host(`blogfr.p2pfoundation.net`)"
- "traefik.http.services.p2p-blogfr.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
blognl:
image: wordpress:6.4-php8.2-apache
container_name: p2p-blognl
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: p2p_blognl
WORDPRESS_DB_USER: p2p_blognl
WORDPRESS_DB_PASSWORD: blognl_secure_2025
volumes:
- blognl_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./robots.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
- ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-blognl.rule=Host(`blognl.p2pfoundation.net`)"
- "traefik.http.services.p2p-blognl.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
web:
image: wordpress:6.4-php8.2-apache
container_name: p2p-web
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: p2p_web
WORDPRESS_DB_USER: p2p_web
WORDPRESS_DB_PASSWORD: web_secure_2025
volumes:
- web_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
- ./robots.txt:/var/www/html/robots.txt:ro
- ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
- ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
depends_on:
db:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.p2p-web.rule=Host(`p2pfoundation.net`) || Host(`www.p2pfoundation.net`)"
- "traefik.http.services.p2p-web.loadbalancer.server.port=80"
networks:
- p2p-internal
- traefik-public
volumes:
db_data:
wiki_data:
blog_data:
bloggr_data:
blogfr_data:
blognl_data:
web_data:
networks:
p2p-internal:
driver: bridge
traefik-public:
external: true

51
blog_static/nginx.conf Normal file
View File

@ -0,0 +1,51 @@
server {
listen 80;
server_name blog.p2pfoundation.net localhost;
# Default index file
index _index_ssl.html index.html;
# Serve WordPress core includes (CSS, JS, images)
location /wp-includes/ {
alias /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-includes/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Serve wp-content assets (themes, uploads, minified CSS/JS)
location /wp-content/ {
alias /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-content/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Health check endpoint
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
# Main location - serve cached pages
location / {
root /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-content/cache/page_enhanced/blog.p2pfoundation.net;
try_files $uri/_index_ssl.html $uri/ $uri =404;
}
# Error pages
error_page 404 /404.html;
location = /404.html {
internal;
return 404 '<!DOCTYPE html><html><head><title>404 - Page Not Found</title></head><body><h1>Page Not Found</h1><p>The requested blog post could not be found.</p><p><a href="/">Return to homepage</a></p></body></html>';
add_header Content-Type text/html;
}
# Inject Umami analytics (rData) into all HTML pages
sub_filter '</head>' '<script defer src="https://rdata.online/collect.js" data-website-id="1faf3e11-797c-4733-90c3-c7f11a2592c5"></script></head>';
sub_filter_once on;
sub_filter_types text/html;
# Gzip compression
gzip on;
gzip_types text/plain text/html text/css application/javascript application/json;
gzip_min_length 1000;
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Plugin Name: rData Analytics (Umami)
* Description: Injects self-hosted Umami analytics tracking script.
* Version: 1.0
*/
add_action('wp_head', function () {
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
if (strpos($host, 'blog.p2pfoundation') !== false) {
$id = '1faf3e11-797c-4733-90c3-c7f11a2592c5';
} else {
$id = '818b3200-081b-470d-a7e6-b1c25c367ff8';
}
echo '<script defer src="https://rdata.online/collect.js" data-website-id="' . esc_attr($id) . '"></script>' . "\n";
}, 1);

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>P2P Wiki AI</title>
<script defer src="https://rdata.online/collect.js" data-website-id="81ed3b8a-ab76-4286-8602-03d15edf237c"></script>
<style>
:root {
--bg-primary: #1a1a2e;