claude-plugin-wordpress-manager 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/CHANGELOG.md +21 -0
  3. package/agents/wp-content-strategist.md +25 -0
  4. package/agents/wp-ecommerce-manager.md +23 -0
  5. package/agents/wp-site-manager.md +26 -0
  6. package/package.json +8 -3
  7. package/skills/wordpress-router/references/decision-tree.md +8 -2
  8. package/skills/wp-content/SKILL.md +1 -0
  9. package/skills/wp-content-attribution/SKILL.md +97 -0
  10. package/skills/wp-content-attribution/references/attribution-models.md +189 -0
  11. package/skills/wp-content-attribution/references/conversion-funnels.md +137 -0
  12. package/skills/wp-content-attribution/references/reporting-dashboards.md +199 -0
  13. package/skills/wp-content-attribution/references/roi-calculation.md +202 -0
  14. package/skills/wp-content-attribution/references/utm-tracking-setup.md +161 -0
  15. package/skills/wp-content-attribution/scripts/attribution_inspect.mjs +277 -0
  16. package/skills/wp-headless/SKILL.md +1 -0
  17. package/skills/wp-i18n/SKILL.md +1 -0
  18. package/skills/wp-multilang-network/SKILL.md +107 -0
  19. package/skills/wp-multilang-network/references/content-sync.md +182 -0
  20. package/skills/wp-multilang-network/references/hreflang-config.md +198 -0
  21. package/skills/wp-multilang-network/references/language-routing.md +234 -0
  22. package/skills/wp-multilang-network/references/network-architecture.md +119 -0
  23. package/skills/wp-multilang-network/references/seo-international.md +213 -0
  24. package/skills/wp-multilang-network/scripts/multilang_inspect.mjs +308 -0
  25. package/skills/wp-multisite/SKILL.md +1 -0
  26. package/skills/wp-programmatic-seo/SKILL.md +97 -0
  27. package/skills/wp-programmatic-seo/references/data-sources.md +200 -0
  28. package/skills/wp-programmatic-seo/references/location-seo.md +134 -0
  29. package/skills/wp-programmatic-seo/references/product-seo.md +147 -0
  30. package/skills/wp-programmatic-seo/references/technical-seo.md +197 -0
  31. package/skills/wp-programmatic-seo/references/template-architecture.md +125 -0
  32. package/skills/wp-programmatic-seo/scripts/programmatic_seo_inspect.mjs +264 -0
  33. package/skills/wp-woocommerce/SKILL.md +1 -0
@@ -0,0 +1,199 @@
1
+ # Reporting Dashboards
2
+
3
+ Use this file when setting up content attribution reporting — GA4 integration, analytics plugin configuration, dashboard KPIs, and automated reporting workflows.
4
+
5
+ ## WooCommerce + WordPress Analytics Correlation
6
+
7
+ The core reporting methodology links three data sources:
8
+
9
+ ```
10
+ WordPress Content Data WooCommerce Order Data Analytics Data
11
+ (list_content, post dates) + (wc_list_orders, order meta) + (GA4, MonsterInsights)
12
+ │ │ │
13
+ └──────────── Correlate via UTM campaign = post slug ─────────┘
14
+ ```
15
+
16
+ ### Manual Correlation Workflow
17
+
18
+ 1. **Export orders** with UTM meta for the reporting period
19
+ 2. **Export content** published in the same period
20
+ 3. **Match** `_last_utm_campaign` values to post slugs
21
+ 4. **Aggregate** revenue per post, per category, per content type
22
+ 5. **Rank** by revenue, ROI, or conversion rate
23
+
24
+ ## Google Analytics 4 Integration
25
+
26
+ ### UTM → GA4 → WooCommerce Reconciliation
27
+
28
+ GA4 automatically captures UTM parameters as session-level dimensions:
29
+
30
+ | GA4 Dimension | UTM Parameter | Use |
31
+ |---------------|--------------|-----|
32
+ | Session source | `utm_source` | Where traffic came from |
33
+ | Session medium | `utm_medium` | Channel type |
34
+ | Session campaign | `utm_campaign` | Specific campaign/post |
35
+ | Session manual ad content | `utm_content` | Link variant |
36
+ | Session manual term | `utm_term` | Search keyword |
37
+
38
+ **GA4 Exploration report for content attribution:**
39
+ 1. Go to Explore → Free-form
40
+ 2. Dimensions: Session campaign, Landing page
41
+ 3. Metrics: Sessions, Conversions, Revenue
42
+ 4. Filter: Session source = "blog"
43
+ 5. Sort by Revenue descending
44
+
45
+ ### Enhanced E-commerce Events
46
+
47
+ GA4 tracks the full purchase funnel when configured:
48
+ - `view_item` — product page view
49
+ - `add_to_cart` — item added to cart
50
+ - `begin_checkout` — checkout started
51
+ - `purchase` — order completed with revenue
52
+
53
+ ## MonsterInsights / WooCommerce Google Analytics Plugin
54
+
55
+ ### MonsterInsights Setup
56
+
57
+ MonsterInsights bridges WordPress content data with GA4:
58
+
59
+ 1. **Install:** MonsterInsights plugin (free tier sufficient for basic attribution)
60
+ 2. **Connect:** Link to GA4 property via the setup wizard
61
+ 3. **Enable:** Enhanced E-commerce tracking in MonsterInsights settings
62
+ 4. **Dashboard:** View top posts by revenue directly in WordPress admin
63
+
64
+ **Key MonsterInsights reports:**
65
+ - Top Landing Pages (awareness stage)
66
+ - Top Outbound Links (consideration stage)
67
+ - E-commerce Revenue by Source (attribution)
68
+ - Top Products (conversion stage)
69
+
70
+ ### WooCommerce Google Analytics Plugin (Official)
71
+
72
+ Alternative for sites already using GA4 without MonsterInsights:
73
+
74
+ 1. Install: "WooCommerce Google Analytics" (official extension)
75
+ 2. Enter GA4 Measurement ID
76
+ 3. Enable: Enhanced E-commerce events
77
+ 4. Events auto-tracked: `view_item`, `add_to_cart`, `purchase`
78
+
79
+ ## Custom Dashboard Options
80
+
81
+ ### WP Admin Dashboard Widget
82
+
83
+ Create a simple attribution summary widget:
84
+
85
+ ```php
86
+ add_action('wp_dashboard_setup', function () {
87
+ wp_add_dashboard_widget(
88
+ 'content_attribution_widget',
89
+ 'Content Attribution — Top 5 Posts by Revenue',
90
+ function () {
91
+ // Query recent completed orders with UTM data
92
+ $orders = wc_get_orders([
93
+ 'status' => 'completed',
94
+ 'limit' => 100,
95
+ 'date_created' => '>' . date('Y-m-d', strtotime('-30 days')),
96
+ ]);
97
+ $revenue_by_campaign = [];
98
+ foreach ($orders as $order) {
99
+ $campaign = $order->get_meta('_last_utm_campaign');
100
+ if ($campaign) {
101
+ $revenue_by_campaign[$campaign] = ($revenue_by_campaign[$campaign] ?? 0) + $order->get_total();
102
+ }
103
+ }
104
+ arsort($revenue_by_campaign);
105
+ echo '<table><tr><th>Content</th><th>Revenue</th></tr>';
106
+ $i = 0;
107
+ foreach ($revenue_by_campaign as $campaign => $revenue) {
108
+ if ($i++ >= 5) break;
109
+ echo '<tr><td>' . esc_html($campaign) . '</td><td>' . wc_price($revenue) . '</td></tr>';
110
+ }
111
+ echo '</table>';
112
+ }
113
+ );
114
+ });
115
+ ```
116
+
117
+ ### External BI Tools
118
+
119
+ For larger operations, export data to external dashboards:
120
+
121
+ | Tool | Integration Method | Cost |
122
+ |------|-------------------|------|
123
+ | Google Looker Studio | GA4 connector + WC data export | Free |
124
+ | Tableau | WooCommerce REST API → CSV/database | Paid |
125
+ | Metabase | Direct MySQL/PostgreSQL connection | Free (self-hosted) |
126
+ | Power BI | REST API connector or CSV import | Paid |
127
+
128
+ ## Automated Reporting
129
+
130
+ ### Monthly Content Attribution Report Template
131
+
132
+ ```
133
+ ## Content Attribution Report — {Month} {Year}
134
+
135
+ ### Summary
136
+ - Total content-attributed revenue: ${total}
137
+ - Orders with UTM attribution: {count} ({percentage}% of total orders)
138
+ - Top attribution model used: {model}
139
+
140
+ ### Top 10 Converting Content Pieces
141
+ | Rank | Post | Revenue | Orders | Avg Order Value |
142
+ |------|------|---------|--------|-----------------|
143
+ | 1 | {title} | ${rev} | {n} | ${aov} |
144
+ | ... | ... | ... | ... | ... |
145
+
146
+ ### Revenue by Content Category
147
+ | Category | Revenue | Posts | Revenue/Post |
148
+ |----------|---------|-------|-------------|
149
+ | {cat} | ${rev} | {n} | ${rpp} |
150
+
151
+ ### Revenue by Source
152
+ | Source | Revenue | Orders | CAC |
153
+ |--------|---------|--------|-----|
154
+ | blog | ${rev} | {n} | ${cac} |
155
+ | newsletter | ${rev} | {n} | ${cac} |
156
+
157
+ ### Recommendations
158
+ - Invest more in: {top category}
159
+ - Reduce investment in: {lowest ROI category}
160
+ - Content gap: {opportunity identified}
161
+ ```
162
+
163
+ ### Automation via WP-Cron
164
+
165
+ Schedule monthly report generation:
166
+
167
+ ```php
168
+ // Register cron event
169
+ if (!wp_next_scheduled('generate_attribution_report')) {
170
+ wp_schedule_event(time(), 'monthly', 'generate_attribution_report');
171
+ }
172
+
173
+ add_action('generate_attribution_report', function () {
174
+ // Generate report data (query orders, correlate with content)
175
+ // Save as a private post or send via email
176
+ // Uses same logic as dashboard widget but for full month
177
+ });
178
+ ```
179
+
180
+ ## Key KPIs Dashboard
181
+
182
+ The essential metrics for an at-a-glance attribution dashboard:
183
+
184
+ | KPI | Description | Update Frequency |
185
+ |-----|-------------|-----------------|
186
+ | **Content-Attributed Revenue** | Total revenue from orders with UTM data | Weekly |
187
+ | **Top Converting Post** | Post with highest attributed revenue this month | Monthly |
188
+ | **Attribution Rate** | % of orders with UTM attribution data | Weekly |
189
+ | **Content ROI** | (Revenue - Cost) / Cost × 100% | Monthly |
190
+ | **CAC by Source** | Customer acquisition cost per channel | Monthly |
191
+ | **Revenue/Post Trend** | Month-over-month revenue per post | Monthly |
192
+
193
+ ## Decision Checklist
194
+
195
+ 1. Is GA4 connected and tracking enhanced e-commerce events? → Verify in GA4 Realtime report
196
+ 2. Is MonsterInsights or equivalent analytics plugin active? → Check WordPress admin dashboard
197
+ 3. Are WooCommerce orders showing UTM meta data? → Spot-check 5 recent orders
198
+ 4. Is a monthly report process defined (manual or automated)? → Set up template + schedule
199
+ 5. Are KPIs reviewed and actioned on regularly? → Schedule monthly review meeting
@@ -0,0 +1,202 @@
1
+ # ROI Calculation
2
+
3
+ Use this file when calculating content return on investment — revenue per post, content ROI formula, customer acquisition cost, and lifetime value by content source.
4
+
5
+ ## Revenue Per Post
6
+
7
+ The most straightforward content attribution metric.
8
+
9
+ **Formula:**
10
+ ```
11
+ Revenue Per Post = Total attributed revenue / Number of posts
12
+ ```
13
+
14
+ **Per-post attribution (last-touch):**
15
+ ```
16
+ Revenue(Post X) = SUM(order_total) WHERE _last_utm_campaign = "post-x-slug"
17
+ ```
18
+
19
+ **Per-post attribution (first-touch):**
20
+ ```
21
+ Revenue(Post X) = SUM(order_total) WHERE _first_utm_campaign = "post-x-slug"
22
+ ```
23
+
24
+ ### Calculating with WooCommerce MCP Tools
25
+
26
+ ```bash
27
+ # Step 1: Get completed orders for the period
28
+ wc_list_orders(status="completed", after="2025-01-01", before="2025-01-31", per_page=100)
29
+
30
+ # Step 2: For each order, read utm meta
31
+ # Group orders by _last_utm_campaign value
32
+ # Sum order_total per campaign (campaign = post slug)
33
+
34
+ # Step 3: Get content list for the same period
35
+ list_content(type="post", status="publish", after="2025-01-01", before="2025-01-31")
36
+
37
+ # Step 4: Match campaign slugs to post titles
38
+ # Result: { post_title: "Cactus Water Benefits", slug: "cactus-water-benefits", revenue: 2500, orders: 15 }
39
+ ```
40
+
41
+ ### Revenue Per Post Benchmarks
42
+
43
+ | Content Type | Typical Revenue/Post | Notes |
44
+ |-------------|---------------------|-------|
45
+ | Product review | $500–$5,000 | High intent, bottom-of-funnel |
46
+ | How-to guide | $100–$1,000 | Indirect conversion, builds trust |
47
+ | Comparison post | $1,000–$10,000 | Very high intent, decision-stage |
48
+ | Category guide | $200–$2,000 | Mid-funnel, product discovery |
49
+ | News/update | $50–$500 | Low intent, brand awareness |
50
+
51
+ ## Content ROI Formula
52
+
53
+ **Formula:**
54
+ ```
55
+ Content ROI = (Revenue - Content Cost) / Content Cost × 100%
56
+ ```
57
+
58
+ **Example:**
59
+ ```
60
+ Blog post cost: $200 (writer) + $50 (images) + $30 (editing) = $280
61
+ Revenue attributed: $1,400 (last-touch, 3 months)
62
+ Content ROI: ($1,400 - $280) / $280 × 100% = 400% ROI
63
+ ```
64
+
65
+ ### Content Cost Components
66
+
67
+ | Component | Typical Cost | How to Track |
68
+ |-----------|-------------|--------------|
69
+ | Writing | $0.10–$0.50/word | Per-post invoice or hourly rate |
70
+ | Editing | $25–$100/post | Editor time tracking |
71
+ | Images/media | $10–$100/post | Stock photo licenses, design time |
72
+ | SEO optimization | $25–$75/post | SEO tool costs + specialist time |
73
+ | Publishing/formatting | $15–$30/post | CMS time |
74
+ | **Total typical cost** | **$100–$500/post** | Sum all components |
75
+
76
+ ### ROI by Content Category
77
+
78
+ Track ROI by category to identify the most profitable content pillars:
79
+
80
+ ```
81
+ Category Posts Total Cost Total Revenue ROI
82
+ ──────────────────────────────────────────────────────
83
+ Product reviews 10 $3,000 $25,000 733%
84
+ How-to guides 20 $4,000 $8,000 100%
85
+ Company news 15 $1,500 $750 -50%
86
+ Case studies 5 $2,500 $12,000 380%
87
+ ```
88
+
89
+ **Action:** Double down on product reviews and case studies; reduce company news investment.
90
+
91
+ ## Customer Acquisition Cost (CAC) by Content Type
92
+
93
+ **Formula:**
94
+ ```
95
+ CAC = Total content investment / New customers acquired from content
96
+ ```
97
+
98
+ **By content type:**
99
+ ```
100
+ CAC(blog) = Blog content costs / New customers with _first_utm_source = "blog"
101
+ CAC(email) = Email costs / New customers with _first_utm_source = "newsletter"
102
+ CAC(social) = Social costs / New customers with _first_utm_source = "facebook|instagram"
103
+ ```
104
+
105
+ ### CAC Benchmarks (E-commerce)
106
+
107
+ | Channel | Typical CAC | Notes |
108
+ |---------|------------|-------|
109
+ | Organic blog content | $20–$80 | Lower CAC, longer to build |
110
+ | Email newsletter | $10–$40 | Lowest CAC, requires list |
111
+ | Paid search (Google) | $30–$100 | Immediate but expensive |
112
+ | Social media (organic) | $25–$75 | Variable, platform-dependent |
113
+ | Social media (paid) | $15–$60 | Scalable with budget |
114
+
115
+ ## Lifetime Value (LTV) by Acquisition Source
116
+
117
+ **Formula:**
118
+ ```
119
+ LTV = Average Order Value × Purchase Frequency × Customer Lifespan
120
+ ```
121
+
122
+ **By source:**
123
+ ```
124
+ LTV(blog) = AOV(blog customers) × Frequency(blog customers) × Lifespan(blog customers)
125
+ ```
126
+
127
+ ### Calculating with WooCommerce Data
128
+
129
+ ```bash
130
+ # Get top sellers to understand AOV patterns
131
+ wc_get_top_sellers(period="year")
132
+
133
+ # Get sales report for overall metrics
134
+ wc_get_sales_report(period="year")
135
+ # Returns: total_sales, total_orders → AOV = total_sales / total_orders
136
+
137
+ # For source-specific LTV:
138
+ # 1. Filter orders by _first_utm_source
139
+ # 2. Group by customer_id
140
+ # 3. Calculate per-customer: total_spent, order_count, first_order_date, last_order_date
141
+ # 4. Average across customers from that source
142
+ ```
143
+
144
+ ### LTV:CAC Ratio
145
+
146
+ ```
147
+ Healthy ratio: LTV:CAC > 3:1
148
+
149
+ Example:
150
+ Blog customers: LTV = $240, CAC = $50 → Ratio = 4.8:1 ✓ Excellent
151
+ Paid ad customers: LTV = $180, CAC = $80 → Ratio = 2.25:1 ⚠ Below target
152
+ ```
153
+
154
+ **Action:** If LTV:CAC < 3:1, either reduce acquisition cost or increase customer retention/upsell.
155
+
156
+ ## Content Efficiency Metrics
157
+
158
+ ### Revenue Per Word
159
+
160
+ ```
161
+ Revenue Per Word = Total attributed revenue / Total words published
162
+ ```
163
+
164
+ Useful for comparing content formats: long-form guides vs short product reviews.
165
+
166
+ ### Revenue Per Topic
167
+
168
+ ```
169
+ Revenue Per Topic = SUM(revenue of posts in topic cluster) / Number of posts in cluster
170
+ ```
171
+
172
+ Identifies which topic clusters are most commercially valuable.
173
+
174
+ ### Time to ROI
175
+
176
+ ```
177
+ Time to ROI = Days from publish date to break-even (revenue ≥ content cost)
178
+ ```
179
+
180
+ Short time to ROI = content with immediate commercial intent (product reviews).
181
+ Long time to ROI = evergreen SEO content (compounds over months).
182
+
183
+ ## Using WC Reports for Date Correlation
184
+
185
+ ```bash
186
+ # Monthly sales report
187
+ wc_get_sales_report(date_min="2025-03-01", date_max="2025-03-31")
188
+
189
+ # Top-selling products in the period
190
+ wc_get_top_sellers(date_min="2025-03-01", date_max="2025-03-31")
191
+
192
+ # Cross-reference with content published before the period:
193
+ list_content(type="post", status="publish", before="2025-03-31", orderby="date", order="desc", per_page=20)
194
+ ```
195
+
196
+ ## Decision Checklist
197
+
198
+ 1. Is content cost tracked per post? → Set up cost tracking (spreadsheet or custom field)
199
+ 2. Is revenue attributed to individual posts via UTM? → Verify mu-plugin capturing data
200
+ 3. Is CAC calculated by acquisition source? → Group orders by first-touch source
201
+ 4. Is LTV:CAC ratio above 3:1? → If not, optimize acquisition or retention
202
+ 5. Are content investments being shifted to highest-ROI categories? → Review quarterly
@@ -0,0 +1,161 @@
1
+ # UTM Tracking Setup
2
+
3
+ Use this file when setting up UTM parameter capture for WooCommerce orders — parameter architecture, mu-plugin installation, naming conventions, and verification.
4
+
5
+ ## UTM Parameter Architecture
6
+
7
+ | Parameter | Purpose | Example |
8
+ |-----------|---------|---------|
9
+ | `utm_source` | Where traffic originates | `blog`, `newsletter`, `google`, `facebook` |
10
+ | `utm_medium` | Marketing channel type | `organic`, `email`, `cpc`, `social`, `referral` |
11
+ | `utm_campaign` | Specific campaign name | `spring-sale-2025`, `product-launch-x` |
12
+ | `utm_content` | Differentiates ad/link variants | `cta-button`, `sidebar-banner`, `post-footer` |
13
+ | `utm_term` | Paid search keywords | `cactus-water-buy`, `zero-calorie-drink` |
14
+
15
+ ## mu-plugin Pattern: Capture UTM on Checkout
16
+
17
+ Create a mu-plugin to automatically capture UTM parameters from the visitor session and store them as WooCommerce order meta:
18
+
19
+ ```php
20
+ <?php
21
+ /**
22
+ * Plugin Name: UTM Order Attribution
23
+ * Description: Captures UTM parameters from visitor session and stores as order meta.
24
+ * Version: 1.0.0
25
+ */
26
+
27
+ // Store UTM params in session cookie on first visit
28
+ add_action('init', function () {
29
+ if (!is_admin() && !wp_doing_cron()) {
30
+ $utm_params = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
31
+ foreach ($utm_params as $param) {
32
+ if (isset($_GET[$param]) && !empty($_GET[$param])) {
33
+ // Store in cookie for 30 days (first-touch attribution)
34
+ $cookie_name = '_wc_' . $param;
35
+ if (!isset($_COOKIE[$cookie_name])) {
36
+ setcookie($cookie_name, sanitize_text_field($_GET[$param]), time() + (30 * DAY_IN_SECONDS), '/');
37
+ }
38
+ // Always update last-touch cookie
39
+ setcookie('_wc_last_' . $param, sanitize_text_field($_GET[$param]), time() + (30 * DAY_IN_SECONDS), '/');
40
+ }
41
+ }
42
+ }
43
+ });
44
+
45
+ // Save UTM data to order meta on checkout
46
+ add_action('woocommerce_checkout_order_processed', function ($order_id) {
47
+ $order = wc_get_order($order_id);
48
+ if (!$order) return;
49
+
50
+ $utm_params = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
51
+ foreach ($utm_params as $param) {
52
+ // Save first-touch
53
+ $first_cookie = '_wc_' . $param;
54
+ if (isset($_COOKIE[$first_cookie]) && !empty($_COOKIE[$first_cookie])) {
55
+ $order->update_meta_data('_first_' . $param, sanitize_text_field($_COOKIE[$first_cookie]));
56
+ }
57
+ // Save last-touch
58
+ $last_cookie = '_wc_last_' . $param;
59
+ if (isset($_COOKIE[$last_cookie]) && !empty($_COOKIE[$last_cookie])) {
60
+ $order->update_meta_data('_last_' . $param, sanitize_text_field($_COOKIE[$last_cookie]));
61
+ }
62
+ }
63
+
64
+ // Save landing page URL (first page visited)
65
+ if (isset($_COOKIE['_wc_landing_page'])) {
66
+ $order->update_meta_data('_landing_page', sanitize_url($_COOKIE['_wc_landing_page']));
67
+ }
68
+
69
+ $order->save();
70
+ });
71
+
72
+ // Track landing page
73
+ add_action('init', function () {
74
+ if (!is_admin() && !wp_doing_cron() && !isset($_COOKIE['_wc_landing_page'])) {
75
+ $landing = esc_url_raw((isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
76
+ setcookie('_wc_landing_page', $landing, time() + (30 * DAY_IN_SECONDS), '/');
77
+ }
78
+ });
79
+ ```
80
+
81
+ **Installation:**
82
+ 1. Save as `wp-content/mu-plugins/utm-order-attribution.php`
83
+ 2. mu-plugins load automatically — no activation needed
84
+ 3. Verify by placing a test order with UTM params in the URL
85
+
86
+ ## UTM Naming Conventions
87
+
88
+ Consistent naming is critical for accurate attribution. Adopt these rules:
89
+
90
+ | Rule | Good | Bad |
91
+ |------|------|-----|
92
+ | Lowercase always | `utm_source=blog` | `utm_source=Blog` |
93
+ | Hyphens for spaces | `spring-sale-2025` | `spring_sale_2025` or `spring sale` |
94
+ | No special chars | `product-launch` | `product_launch!` |
95
+ | Consistent source names | `newsletter` (always) | `email`, `newsletter`, `mail` (mixed) |
96
+ | Date in campaigns | `black-friday-2025` | `black-friday` (ambiguous year) |
97
+
98
+ **Recommended source taxonomy:**
99
+
100
+ | Source | Medium | When to Use |
101
+ |--------|--------|-------------|
102
+ | `blog` | `organic` | Internal blog post links to products |
103
+ | `blog` | `cta` | Blog post CTA buttons to products |
104
+ | `newsletter` | `email` | Email newsletter links |
105
+ | `google` | `cpc` | Google Ads campaigns |
106
+ | `facebook` | `social` | Facebook organic or paid posts |
107
+ | `instagram` | `social` | Instagram bio/stories links |
108
+ | `partner-name` | `referral` | Partner/affiliate links |
109
+
110
+ ## Internal Link UTM Tagging
111
+
112
+ Tag all blog-to-product links with UTMs:
113
+
114
+ ```html
115
+ <!-- Blog post CTA linking to product -->
116
+ <a href="/product/cactus-water/?utm_source=blog&utm_medium=cta&utm_campaign=cactus-water-benefits&utm_content=post-footer-button">
117
+ Buy Cactus Water
118
+ </a>
119
+
120
+ <!-- Sidebar widget linking to product -->
121
+ <a href="/product/cactus-water/?utm_source=blog&utm_medium=sidebar&utm_campaign=always-on&utm_content=product-widget">
122
+ Try Cactus Water
123
+ </a>
124
+ ```
125
+
126
+ **Automated tagging approach:** Use a WordPress filter to append UTMs to all internal product links in post content:
127
+
128
+ ```php
129
+ add_filter('the_content', function ($content) {
130
+ if (!is_singular('post')) return $content;
131
+ $post_slug = get_post_field('post_name', get_the_ID());
132
+ // Append UTM to internal /product/ links that don't already have UTM
133
+ $content = preg_replace_callback(
134
+ '#href="(/product/[^"]*?)(?<!\?[^"]*utm_source[^"]*)"#',
135
+ function ($matches) use ($post_slug) {
136
+ $sep = strpos($matches[1], '?') !== false ? '&' : '?';
137
+ return 'href="' . $matches[1] . $sep . 'utm_source=blog&utm_medium=organic&utm_campaign=' . $post_slug . '"';
138
+ },
139
+ $content
140
+ );
141
+ return $content;
142
+ });
143
+ ```
144
+
145
+ ## Verification
146
+
147
+ After installing the mu-plugin:
148
+
149
+ 1. **Test visit:** Navigate to `yoursite.com/product/example/?utm_source=test&utm_medium=test&utm_campaign=test`
150
+ 2. **Place test order** through WooCommerce checkout
151
+ 3. **Check order meta:** Use `wc_list_orders` MCP tool or WooCommerce admin → Orders → order details
152
+ 4. **Verify fields:** `_first_utm_source`, `_last_utm_source`, `_first_utm_campaign`, etc. should be populated
153
+ 5. **Check cookies:** Browser dev tools → Application → Cookies → look for `_wc_utm_*` cookies
154
+
155
+ ## Decision Checklist
156
+
157
+ 1. Is the mu-plugin installed in `wp-content/mu-plugins/`? → Verify file exists
158
+ 2. Are UTM naming conventions documented for the team? → Share taxonomy table
159
+ 3. Are internal blog→product links tagged with UTMs? → Audit sample posts
160
+ 4. Has a test order been placed with UTM params to verify capture? → Must pass before going live
161
+ 5. Is cookie duration appropriate (30 days default)? → Adjust for sales cycle length