claude-plugin-wordpress-manager 2.3.0 → 2.4.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.
- package/.claude-plugin/plugin.json +8 -3
- package/CHANGELOG.md +25 -0
- package/agents/wp-distribution-manager.md +98 -0
- package/docs/GUIDE.md +126 -10
- package/docs/plans/2026-03-01-tier3-wcop-design.md +373 -0
- package/docs/plans/2026-03-01-tier3-wcop-implementation.md +915 -0
- package/hooks/hooks.json +18 -0
- package/package.json +9 -3
- package/servers/wp-rest-bridge/build/tools/buffer.d.ts +3 -0
- package/servers/wp-rest-bridge/build/tools/buffer.js +205 -0
- package/servers/wp-rest-bridge/build/tools/index.js +9 -0
- package/servers/wp-rest-bridge/build/tools/mailchimp.d.ts +3 -0
- package/servers/wp-rest-bridge/build/tools/mailchimp.js +265 -0
- package/servers/wp-rest-bridge/build/tools/sendgrid.d.ts +3 -0
- package/servers/wp-rest-bridge/build/tools/sendgrid.js +255 -0
- package/servers/wp-rest-bridge/build/types.d.ts +122 -0
- package/servers/wp-rest-bridge/build/wordpress.d.ts +9 -0
- package/servers/wp-rest-bridge/build/wordpress.js +112 -0
- package/skills/wordpress-router/references/decision-tree.md +4 -2
- package/skills/wp-content/SKILL.md +1 -0
- package/skills/wp-content-repurposing/SKILL.md +1 -0
- package/skills/wp-social-email/SKILL.md +152 -0
- package/skills/wp-social-email/references/audience-segmentation.md +173 -0
- package/skills/wp-social-email/references/buffer-social-publishing.md +124 -0
- package/skills/wp-social-email/references/content-to-distribution.md +156 -0
- package/skills/wp-social-email/references/distribution-analytics.md +208 -0
- package/skills/wp-social-email/references/mailchimp-integration.md +145 -0
- package/skills/wp-social-email/references/sendgrid-transactional.md +165 -0
- package/skills/wp-social-email/scripts/distribution_inspect.mjs +165 -0
- package/skills/wp-webhooks/SKILL.md +1 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Distribution Analytics
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Distribution analytics measure the effectiveness of content distributed across email (Mailchimp, SendGrid) and social (Buffer) channels. Tracking performance per channel enables data-driven decisions on content strategy, send timing, and audience targeting.
|
|
6
|
+
|
|
7
|
+
## Mailchimp Campaign Reports
|
|
8
|
+
|
|
9
|
+
### Get campaign performance
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Tool: mc_get_campaign_report
|
|
13
|
+
Params:
|
|
14
|
+
campaign_id: "campaign_xyz"
|
|
15
|
+
Returns:
|
|
16
|
+
emails_sent: 1250
|
|
17
|
+
opens:
|
|
18
|
+
total: 487
|
|
19
|
+
unique: 412
|
|
20
|
+
rate: 0.33
|
|
21
|
+
clicks:
|
|
22
|
+
total: 98
|
|
23
|
+
unique: 76
|
|
24
|
+
rate: 0.061
|
|
25
|
+
bounces:
|
|
26
|
+
hard: 3
|
|
27
|
+
soft: 12
|
|
28
|
+
unsubscribes: 2
|
|
29
|
+
forwards: 5
|
|
30
|
+
abuse_reports: 0
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Key Mailchimp metrics
|
|
34
|
+
|
|
35
|
+
| Metric | Calculation | Benchmark |
|
|
36
|
+
|--------|-------------|-----------|
|
|
37
|
+
| Open rate | Unique opens / Delivered | 20-25% |
|
|
38
|
+
| Click rate | Unique clicks / Delivered | 2.5-5% |
|
|
39
|
+
| Click-to-open rate | Unique clicks / Unique opens | 10-15% |
|
|
40
|
+
| Bounce rate | (Hard + Soft bounces) / Sent | < 2% |
|
|
41
|
+
| Unsubscribe rate | Unsubscribes / Delivered | < 0.5% |
|
|
42
|
+
| List growth rate | (New - Unsubscribes) / Total | > 2% monthly |
|
|
43
|
+
|
|
44
|
+
### Analyzing campaign trends
|
|
45
|
+
|
|
46
|
+
Compare multiple campaigns to identify patterns:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
# Fetch reports for recent campaigns
|
|
50
|
+
mc_get_campaign_report campaign_id="campaign_1" → { open_rate: 0.28, click_rate: 0.04 }
|
|
51
|
+
mc_get_campaign_report campaign_id="campaign_2" → { open_rate: 0.35, click_rate: 0.07 }
|
|
52
|
+
mc_get_campaign_report campaign_id="campaign_3" → { open_rate: 0.22, click_rate: 0.03 }
|
|
53
|
+
|
|
54
|
+
# Campaign 2 outperformed — analyze: subject line? send time? content type?
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Buffer Analytics
|
|
58
|
+
|
|
59
|
+
### Get social profile analytics
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Tool: buf_get_analytics
|
|
63
|
+
Params:
|
|
64
|
+
profile_id: "profile_abc123"
|
|
65
|
+
Returns:
|
|
66
|
+
posts_count: 45
|
|
67
|
+
total_reach: 12500
|
|
68
|
+
total_engagement: 890
|
|
69
|
+
total_clicks: 234
|
|
70
|
+
per_post_average:
|
|
71
|
+
reach: 278
|
|
72
|
+
engagement: 19.8
|
|
73
|
+
clicks: 5.2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Key Buffer metrics
|
|
77
|
+
|
|
78
|
+
| Metric | Description | Benchmark |
|
|
79
|
+
|--------|-------------|-----------|
|
|
80
|
+
| Reach | Number of unique users who saw the post | Varies by platform |
|
|
81
|
+
| Engagement | Likes + comments + shares + retweets | 1-3% of reach |
|
|
82
|
+
| Engagement rate | Engagement / Reach | 1-5% (varies by platform) |
|
|
83
|
+
| Clicks | Link clicks from post | 0.5-2% of reach |
|
|
84
|
+
| Click-through rate | Clicks / Reach | 1-3% |
|
|
85
|
+
| Best time to post | Time slot with highest engagement | Platform-specific |
|
|
86
|
+
|
|
87
|
+
### Identifying top-performing content
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Tool: buf_list_sent
|
|
91
|
+
Params:
|
|
92
|
+
profile_id: "profile_abc123"
|
|
93
|
+
count: 50
|
|
94
|
+
|
|
95
|
+
# Sort results by engagement metrics to find top performers
|
|
96
|
+
# Re-share top content using buf_create_update with updated text
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## SendGrid Statistics
|
|
100
|
+
|
|
101
|
+
### Get email delivery stats
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Tool: sg_get_stats
|
|
105
|
+
Params:
|
|
106
|
+
start_date: "2026-03-01"
|
|
107
|
+
end_date: "2026-03-15"
|
|
108
|
+
Returns:
|
|
109
|
+
- date: "2026-03-01"
|
|
110
|
+
metrics:
|
|
111
|
+
requests: 150
|
|
112
|
+
delivered: 148
|
|
113
|
+
opens: 52
|
|
114
|
+
unique_opens: 45
|
|
115
|
+
clicks: 12
|
|
116
|
+
unique_clicks: 10
|
|
117
|
+
bounces: 2
|
|
118
|
+
spam_reports: 0
|
|
119
|
+
blocks: 0
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Key SendGrid metrics
|
|
123
|
+
|
|
124
|
+
| Metric | Calculation | Benchmark |
|
|
125
|
+
|--------|-------------|-----------|
|
|
126
|
+
| Delivery rate | Delivered / Requests | > 95% |
|
|
127
|
+
| Open rate | Unique opens / Delivered | 15-25% (transactional: 40-60%) |
|
|
128
|
+
| Click rate | Unique clicks / Delivered | 2-5% |
|
|
129
|
+
| Bounce rate | Bounces / Requests | < 3% |
|
|
130
|
+
| Spam complaint rate | Spam reports / Delivered | < 0.1% |
|
|
131
|
+
| Block rate | Blocks / Requests | < 1% |
|
|
132
|
+
|
|
133
|
+
### Transactional vs marketing benchmarks
|
|
134
|
+
|
|
135
|
+
Transactional emails (welcome, order confirmation) consistently outperform marketing emails:
|
|
136
|
+
|
|
137
|
+
| Type | Open Rate | Click Rate |
|
|
138
|
+
|------|-----------|------------|
|
|
139
|
+
| Transactional | 40-60% | 10-20% |
|
|
140
|
+
| Marketing | 15-25% | 2-5% |
|
|
141
|
+
|
|
142
|
+
## Cross-Channel Performance Comparison
|
|
143
|
+
|
|
144
|
+
### Unified metrics dashboard
|
|
145
|
+
|
|
146
|
+
Build a cross-channel view by combining data from all three services:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
# Email (Mailchimp campaigns)
|
|
150
|
+
mc_get_campaign_report → opens, clicks, unsubscribes
|
|
151
|
+
|
|
152
|
+
# Social (Buffer)
|
|
153
|
+
buf_get_analytics → reach, engagement, clicks
|
|
154
|
+
|
|
155
|
+
# Transactional (SendGrid)
|
|
156
|
+
sg_get_stats → deliveries, opens, clicks
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Channel comparison table
|
|
160
|
+
|
|
161
|
+
| Channel | Reach | Engagement Rate | Click Rate | Cost per Click |
|
|
162
|
+
|---------|-------|-----------------|------------|----------------|
|
|
163
|
+
| Email (Mailchimp) | Audience size | Open rate 20-25% | 2.5-5% | Low |
|
|
164
|
+
| Social (Buffer) | Follower count + viral | 1-5% | 0.5-2% | Free (organic) |
|
|
165
|
+
| Transactional (SendGrid) | Per-event | 40-60% open | 10-20% | Per email |
|
|
166
|
+
|
|
167
|
+
### Attribution tracking
|
|
168
|
+
|
|
169
|
+
Use UTM parameters to track which channel drives conversions in WordPress/WooCommerce:
|
|
170
|
+
|
|
171
|
+
| Channel | UTM Source | UTM Medium | UTM Campaign |
|
|
172
|
+
|---------|-----------|------------|--------------|
|
|
173
|
+
| Mailchimp | `mailchimp` | `email` | `{campaign_name}` |
|
|
174
|
+
| Buffer | `buffer` | `social` | `{post_slug}` |
|
|
175
|
+
| SendGrid | `sendgrid` | `email` | `{template_name}` |
|
|
176
|
+
|
|
177
|
+
## KPIs and Benchmarks
|
|
178
|
+
|
|
179
|
+
### Weekly KPIs to track
|
|
180
|
+
|
|
181
|
+
| KPI | Target | Tool |
|
|
182
|
+
|-----|--------|------|
|
|
183
|
+
| Email open rate | > 22% | `mc_get_campaign_report` |
|
|
184
|
+
| Email click rate | > 3% | `mc_get_campaign_report` |
|
|
185
|
+
| Social engagement rate | > 2% | `buf_get_analytics` |
|
|
186
|
+
| Email delivery rate | > 95% | `sg_get_stats` |
|
|
187
|
+
| List growth (net) | > 50/week | `mc_get_audience_members` count delta |
|
|
188
|
+
| Content distributed | 3+ posts/week | Track distribution events |
|
|
189
|
+
|
|
190
|
+
### Red flags requiring action
|
|
191
|
+
|
|
192
|
+
| Signal | Threshold | Action |
|
|
193
|
+
|--------|-----------|--------|
|
|
194
|
+
| Open rate drop | < 15% | Review subject lines, check deliverability |
|
|
195
|
+
| High unsubscribe rate | > 0.5% | Reduce frequency, improve segmentation |
|
|
196
|
+
| Bounce rate spike | > 5% | Clean list, verify new signups |
|
|
197
|
+
| Spam complaints | > 0.1% | Review content, check opt-in process |
|
|
198
|
+
| Social engagement decline | < 0.5% | Refresh content format, test new posting times |
|
|
199
|
+
| Delivery blocks | > 1% | Check domain reputation, review SPF/DKIM |
|
|
200
|
+
|
|
201
|
+
## Best Practices
|
|
202
|
+
|
|
203
|
+
- **Weekly review cadence**: Pull analytics every Monday; compare to previous week and 4-week average
|
|
204
|
+
- **A/B test systematically**: Test one variable at a time (subject line, send time, content format) and track results in `mc_get_campaign_report`
|
|
205
|
+
- **Channel-specific goals**: Email optimizes for clicks; social optimizes for engagement; transactional optimizes for delivery
|
|
206
|
+
- **Sunset inactive contacts**: After 90 days of no opens, move contacts to a re-engagement segment or suppress
|
|
207
|
+
- **Document learnings**: Record what subject lines, content types, and send times produce the best results
|
|
208
|
+
- **Automate reporting**: Build a weekly script that calls `mc_get_campaign_report`, `buf_get_analytics`, and `sg_get_stats` to generate a unified report
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Mailchimp Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Mailchimp is the email marketing platform for audience management and campaign delivery. The WP REST Bridge provides 7 MCP tools (`mc_*`) that cover the full campaign lifecycle: audience management, campaign creation, content setting, sending, and reporting.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### API Key Configuration
|
|
10
|
+
|
|
11
|
+
Add Mailchimp credentials to `WP_SITES_CONFIG`:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"sites": [{
|
|
16
|
+
"name": "my-site",
|
|
17
|
+
"url": "https://example.com",
|
|
18
|
+
"distribution": {
|
|
19
|
+
"mailchimp": {
|
|
20
|
+
"api_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us14",
|
|
21
|
+
"server_prefix": "us14"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The server prefix is the suffix of your API key (e.g., `us14`). All Mailchimp API requests route through `https://{server_prefix}.api.mailchimp.com/3.0/`.
|
|
29
|
+
|
|
30
|
+
## Audience Management
|
|
31
|
+
|
|
32
|
+
### List all audiences
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Tool: mc_list_audiences
|
|
36
|
+
Returns: Array of audiences with id, name, member count, stats
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Get audience members
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Tool: mc_get_audience_members
|
|
43
|
+
Params:
|
|
44
|
+
audience_id: "abc123def4"
|
|
45
|
+
count: 50
|
|
46
|
+
offset: 0
|
|
47
|
+
status: "subscribed" # subscribed | unsubscribed | cleaned | pending
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Add a subscriber
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Tool: mc_add_subscriber
|
|
54
|
+
Params:
|
|
55
|
+
audience_id: "abc123def4"
|
|
56
|
+
email: "user@example.com"
|
|
57
|
+
status: "subscribed"
|
|
58
|
+
merge_fields:
|
|
59
|
+
FNAME: "Jane"
|
|
60
|
+
LNAME: "Doe"
|
|
61
|
+
tags: ["wordpress-user", "blog-subscriber"]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If the email already exists, the subscriber record is updated (upsert behavior).
|
|
65
|
+
|
|
66
|
+
## Campaign Workflow
|
|
67
|
+
|
|
68
|
+
The campaign lifecycle follows four steps: create → set content → send → report.
|
|
69
|
+
|
|
70
|
+
### Step 1: Create campaign
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Tool: mc_create_campaign
|
|
74
|
+
Params:
|
|
75
|
+
type: "regular" # regular | plaintext | absplit
|
|
76
|
+
audience_id: "abc123def4"
|
|
77
|
+
subject: "March Newsletter: New Blog Posts"
|
|
78
|
+
from_name: "My Site"
|
|
79
|
+
reply_to: "newsletter@example.com"
|
|
80
|
+
Returns: campaign_id
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Step 2: Set campaign content
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Tool: mc_set_campaign_content
|
|
87
|
+
Params:
|
|
88
|
+
campaign_id: "campaign_xyz"
|
|
89
|
+
html: "<html><body><h1>Newsletter</h1>...</body></html>"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
For WordPress content, fetch the post with `wp_get_post` and format the content as HTML for the campaign body.
|
|
93
|
+
|
|
94
|
+
### Step 3: Send campaign
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Tool: mc_send_campaign
|
|
98
|
+
Params:
|
|
99
|
+
campaign_id: "campaign_xyz"
|
|
100
|
+
# Or schedule for later:
|
|
101
|
+
# schedule_time: "2026-03-15T10:00:00Z"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Step 4: Get report
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Tool: mc_get_campaign_report
|
|
108
|
+
Params:
|
|
109
|
+
campaign_id: "campaign_xyz"
|
|
110
|
+
Returns:
|
|
111
|
+
emails_sent: 1250
|
|
112
|
+
opens: { total: 487, unique: 412, rate: 0.33 }
|
|
113
|
+
clicks: { total: 98, unique: 76, rate: 0.061 }
|
|
114
|
+
bounces: { hard: 3, soft: 12 }
|
|
115
|
+
unsubscribes: 2
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## A/B Testing
|
|
119
|
+
|
|
120
|
+
Create an A/B split campaign to test subject lines, content, or send times:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
Tool: mc_create_campaign
|
|
124
|
+
Params:
|
|
125
|
+
type: "absplit"
|
|
126
|
+
audience_id: "abc123def4"
|
|
127
|
+
subject: "Version A Subject"
|
|
128
|
+
variate_settings:
|
|
129
|
+
test_size: 30 # 30% of audience gets test
|
|
130
|
+
wait_time: 4 # hours before picking winner
|
|
131
|
+
winner_criteria: "opens"
|
|
132
|
+
subject_lines:
|
|
133
|
+
- "Version A Subject"
|
|
134
|
+
- "Version B Subject"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Best Practices
|
|
138
|
+
|
|
139
|
+
- **Send time optimization**: Analyze `mc_get_campaign_report` data to identify peak open hours; schedule campaigns accordingly
|
|
140
|
+
- **List hygiene**: Regularly check for `cleaned` status members; high bounce rates damage sender reputation
|
|
141
|
+
- **Merge fields**: Use `FNAME` personalization in subject lines — personalized subjects see 20-30% higher open rates
|
|
142
|
+
- **Tags over groups**: Use tags for flexible segmentation; they are easier to manage via API than interest groups
|
|
143
|
+
- **Double opt-in**: Enable for GDPR compliance; set subscriber status to `pending` and let Mailchimp handle the confirmation email
|
|
144
|
+
- **Unsubscribe handling**: Never re-add unsubscribed users; check status before calling `mc_add_subscriber`
|
|
145
|
+
- **Frequency**: Monitor unsubscribe rate per campaign; rates above 0.5% indicate over-sending
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# SendGrid Transactional Email
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SendGrid handles transactional email delivery — messages triggered by user actions such as account creation, password resets, order confirmations, and notifications. The WP REST Bridge provides 6 MCP tools (`sg_*`) for sending email, managing templates, and tracking contacts.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### API Key Configuration
|
|
10
|
+
|
|
11
|
+
Add SendGrid credentials to `WP_SITES_CONFIG`:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"sites": [{
|
|
16
|
+
"name": "my-site",
|
|
17
|
+
"url": "https://example.com",
|
|
18
|
+
"distribution": {
|
|
19
|
+
"sendgrid": {
|
|
20
|
+
"api_key": "SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
21
|
+
"from_email": "noreply@example.com",
|
|
22
|
+
"from_name": "My Site"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}]
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use a Restricted Access API key with only the permissions needed (Mail Send, Template Engine, Marketing Contacts).
|
|
30
|
+
|
|
31
|
+
## Transactional Email
|
|
32
|
+
|
|
33
|
+
### Send a plain email
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Tool: sg_send_email
|
|
37
|
+
Params:
|
|
38
|
+
to: "user@example.com"
|
|
39
|
+
subject: "Welcome to My Site"
|
|
40
|
+
html: "<h1>Welcome!</h1><p>Thanks for creating your account.</p>"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Send with a dynamic template
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Tool: sg_send_email
|
|
47
|
+
Params:
|
|
48
|
+
to: "user@example.com"
|
|
49
|
+
template_id: "d-abc123def456"
|
|
50
|
+
dynamic_template_data:
|
|
51
|
+
first_name: "Jane"
|
|
52
|
+
order_number: "WC-1042"
|
|
53
|
+
order_total: "$49.99"
|
|
54
|
+
order_url: "https://example.com/my-account/orders/1042"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Common transactional email types
|
|
58
|
+
|
|
59
|
+
| Type | Trigger | Template Variables |
|
|
60
|
+
|------|---------|-------------------|
|
|
61
|
+
| Welcome email | User registration | `first_name`, `login_url` |
|
|
62
|
+
| Password reset | Password reset request | `reset_link`, `expiry_time` |
|
|
63
|
+
| Order confirmation | WooCommerce order placed | `order_number`, `items`, `total` |
|
|
64
|
+
| Shipping notification | Order status → shipped | `tracking_number`, `carrier`, `eta` |
|
|
65
|
+
| Review request | 7 days after delivery | `product_name`, `review_url` |
|
|
66
|
+
|
|
67
|
+
## Template Management
|
|
68
|
+
|
|
69
|
+
### List templates
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Tool: sg_list_templates
|
|
73
|
+
Params:
|
|
74
|
+
generations: "dynamic" # legacy | dynamic
|
|
75
|
+
Returns: Array of templates with id, name, generation, versions
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Get template details
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Tool: sg_get_template
|
|
82
|
+
Params:
|
|
83
|
+
template_id: "d-abc123def456"
|
|
84
|
+
Returns:
|
|
85
|
+
id, name, generation
|
|
86
|
+
versions: [{ id, name, subject, html_content, active }]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Dynamic templates use Handlebars syntax for variable substitution:
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<h1>Hi {{first_name}},</h1>
|
|
93
|
+
<p>Your order #{{order_number}} has been confirmed.</p>
|
|
94
|
+
{{#if tracking_number}}
|
|
95
|
+
<p>Tracking: {{tracking_number}}</p>
|
|
96
|
+
{{/if}}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Contact Management
|
|
100
|
+
|
|
101
|
+
### List contacts
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Tool: sg_list_contacts
|
|
105
|
+
Params:
|
|
106
|
+
# Optional search query using SGQL
|
|
107
|
+
query: "email LIKE '%@example.com'"
|
|
108
|
+
Returns: Array of contacts with id, email, first_name, last_name, custom_fields
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Add or update contacts
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
Tool: sg_add_contacts
|
|
115
|
+
Params:
|
|
116
|
+
list_ids: ["list_abc123"]
|
|
117
|
+
contacts:
|
|
118
|
+
- email: "user@example.com"
|
|
119
|
+
first_name: "Jane"
|
|
120
|
+
last_name: "Doe"
|
|
121
|
+
custom_fields:
|
|
122
|
+
wp_user_id: "42"
|
|
123
|
+
signup_source: "blog"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Contacts are upserted by email address. If the email already exists, fields are merged.
|
|
127
|
+
|
|
128
|
+
## WordPress Integration Patterns
|
|
129
|
+
|
|
130
|
+
### New user → Welcome email
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
1. WordPress user_register event triggers webhook
|
|
134
|
+
2. Webhook handler calls sg_send_email with welcome template
|
|
135
|
+
3. sg_add_contacts adds user to "New Users" contact list
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### WooCommerce order → Confirmation email
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
1. order.created webhook fires
|
|
142
|
+
2. Extract order details (number, items, total)
|
|
143
|
+
3. sg_send_email with order confirmation template + dynamic data
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Blog subscriber → Drip sequence
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
1. Newsletter form submission adds subscriber via mc_add_subscriber
|
|
150
|
+
2. sg_send_email sends immediate welcome/confirmation
|
|
151
|
+
3. Scheduled follow-ups via campaign automation
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Best Practices
|
|
155
|
+
|
|
156
|
+
- **SPF/DKIM/DMARC**: Configure DNS records for your sending domain; without these, emails land in spam
|
|
157
|
+
- SPF: Add SendGrid's include to your TXT record
|
|
158
|
+
- DKIM: Create CNAME records provided by SendGrid domain authentication
|
|
159
|
+
- DMARC: Start with `p=none` policy, move to `p=quarantine` after monitoring
|
|
160
|
+
- **Dedicated IP**: For volumes above 50k emails/month, use a dedicated IP and warm it gradually (start with 100/day, increase over 4 weeks)
|
|
161
|
+
- **Bounce handling**: Monitor `sg_get_stats` for bounce rates; rates above 5% trigger SendGrid compliance review
|
|
162
|
+
- **Unsubscribe**: Include an unsubscribe link in every email (required by CAN-SPAM); use SendGrid's built-in unsubscribe groups
|
|
163
|
+
- **Template versioning**: Keep templates in version control; use SendGrid's active version feature to deploy changes safely
|
|
164
|
+
- **Rate limiting**: SendGrid enforces rate limits per API key; batch contact additions in groups of 1000
|
|
165
|
+
- **From address consistency**: Use the same `from_email` across all transactional messages to build domain reputation
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* distribution_inspect.mjs — Detect social/email distribution configuration.
|
|
3
|
+
*
|
|
4
|
+
* Checks WP_SITES_CONFIG for connector API keys, WordPress plugins,
|
|
5
|
+
* and content readiness for distribution.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node distribution_inspect.mjs [--cwd=/path/to/project]
|
|
9
|
+
*
|
|
10
|
+
* Exit codes:
|
|
11
|
+
* 0 — distribution configuration found
|
|
12
|
+
* 1 — no distribution configuration found
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
16
|
+
import { join, resolve } from 'node:path';
|
|
17
|
+
import { argv, stdout, exit } from 'node:process';
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Helpers
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
function readFileSafe(filePath) {
|
|
24
|
+
try { return readFileSync(filePath, 'utf-8'); } catch { return null; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function existsSafe(filePath) {
|
|
28
|
+
try { return existsSync(filePath); } catch { return false; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function globDir(dirPath) {
|
|
32
|
+
try { return readdirSync(dirPath); } catch { return []; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Detectors
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
function detectServices() {
|
|
40
|
+
const services = {
|
|
41
|
+
mailchimp: { configured: false, indicators: [] },
|
|
42
|
+
buffer: { configured: false, indicators: [] },
|
|
43
|
+
sendgrid: { configured: false, indicators: [] },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const raw = process.env.WP_SITES_CONFIG;
|
|
47
|
+
if (!raw) return services;
|
|
48
|
+
|
|
49
|
+
let sites;
|
|
50
|
+
try { sites = JSON.parse(raw); } catch { return services; }
|
|
51
|
+
if (!Array.isArray(sites)) return services;
|
|
52
|
+
|
|
53
|
+
for (const site of sites) {
|
|
54
|
+
const label = site.name || site.url || 'unknown';
|
|
55
|
+
|
|
56
|
+
if (site.mailchimp_api_key) {
|
|
57
|
+
services.mailchimp.configured = true;
|
|
58
|
+
services.mailchimp.indicators.push(`mailchimp_api_key configured for ${label}`);
|
|
59
|
+
}
|
|
60
|
+
if (site.buffer_access_token) {
|
|
61
|
+
services.buffer.configured = true;
|
|
62
|
+
services.buffer.indicators.push(`buffer_access_token configured for ${label}`);
|
|
63
|
+
}
|
|
64
|
+
if (site.sendgrid_api_key) {
|
|
65
|
+
services.sendgrid.configured = true;
|
|
66
|
+
services.sendgrid.indicators.push(`sendgrid_api_key configured for ${label}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return services;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function detectDistributionPlugins(cwd) {
|
|
74
|
+
const indicators = [];
|
|
75
|
+
const plugins = globDir(join(cwd, 'wp-content', 'plugins'));
|
|
76
|
+
|
|
77
|
+
const distributionPlugins = [
|
|
78
|
+
'mailchimp-for-wp', 'mc4wp',
|
|
79
|
+
'jetpack',
|
|
80
|
+
'social-warfare', 'monarch', 'shared-counts',
|
|
81
|
+
'newsletter', 'email-subscribers',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
for (const plugin of plugins) {
|
|
85
|
+
if (distributionPlugins.some(dp => plugin.toLowerCase().includes(dp))) {
|
|
86
|
+
indicators.push(`distribution_plugin: ${plugin}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { found: indicators.length > 0, indicators };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function detectContentReadiness(cwd) {
|
|
94
|
+
// Check wp-content directory exists
|
|
95
|
+
if (!existsSafe(join(cwd, 'wp-content'))) return false;
|
|
96
|
+
|
|
97
|
+
// Check for posts/content indicators
|
|
98
|
+
const uploads = globDir(join(cwd, 'wp-content', 'uploads'));
|
|
99
|
+
if (uploads.length > 0) return true;
|
|
100
|
+
|
|
101
|
+
// Check for themes (site is set up)
|
|
102
|
+
const themes = globDir(join(cwd, 'wp-content', 'themes'));
|
|
103
|
+
if (themes.length > 0) return true;
|
|
104
|
+
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Main
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
function main() {
|
|
113
|
+
const cwdArg = argv.find(a => a.startsWith('--cwd='));
|
|
114
|
+
const cwd = cwdArg ? resolve(cwdArg.split('=')[1]) : process.cwd();
|
|
115
|
+
|
|
116
|
+
const services = detectServices();
|
|
117
|
+
const plugins = detectDistributionPlugins(cwd);
|
|
118
|
+
const contentReady = detectContentReadiness(cwd);
|
|
119
|
+
|
|
120
|
+
const hasServices = services.mailchimp.configured ||
|
|
121
|
+
services.buffer.configured ||
|
|
122
|
+
services.sendgrid.configured;
|
|
123
|
+
const found = hasServices || plugins.found;
|
|
124
|
+
|
|
125
|
+
const recommendations = [];
|
|
126
|
+
|
|
127
|
+
if (services.mailchimp.configured) {
|
|
128
|
+
recommendations.push('Mailchimp configured — use distribution_send skill to create and send email campaigns');
|
|
129
|
+
}
|
|
130
|
+
if (services.buffer.configured) {
|
|
131
|
+
recommendations.push('Buffer configured — use distribution_send skill to schedule social media posts');
|
|
132
|
+
}
|
|
133
|
+
if (services.sendgrid.configured) {
|
|
134
|
+
recommendations.push('SendGrid configured — use distribution_send skill for transactional and marketing emails');
|
|
135
|
+
}
|
|
136
|
+
if (plugins.found) {
|
|
137
|
+
recommendations.push('Distribution plugins detected — check plugin settings for additional integration opportunities');
|
|
138
|
+
}
|
|
139
|
+
if (!found) {
|
|
140
|
+
recommendations.push('No distribution configuration detected — use wp-social-email skill to set up Mailchimp, Buffer, or SendGrid');
|
|
141
|
+
}
|
|
142
|
+
if (!contentReady) {
|
|
143
|
+
recommendations.push('No content detected — create posts before setting up distribution workflows');
|
|
144
|
+
}
|
|
145
|
+
if (found && contentReady) {
|
|
146
|
+
recommendations.push('Distribution services and content are ready — consider scheduling an automated campaign');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const report = {
|
|
150
|
+
tool: 'distribution_inspect',
|
|
151
|
+
version: '1.0.0',
|
|
152
|
+
timestamp: new Date().toISOString(),
|
|
153
|
+
cwd,
|
|
154
|
+
found,
|
|
155
|
+
services,
|
|
156
|
+
plugins,
|
|
157
|
+
content_ready: contentReady,
|
|
158
|
+
recommendations,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
162
|
+
exit(found ? 0 : 1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
main();
|
|
@@ -105,3 +105,4 @@ See `references/payload-formats.md`
|
|
|
105
105
|
- **`wp-headless`** — headless revalidation webhooks and ISR triggers
|
|
106
106
|
- **`wp-woocommerce`** — WooCommerce store operations (webhook source events)
|
|
107
107
|
- **`wp-cicd`** — CI/CD webhooks for deployment triggers
|
|
108
|
+
- **wp-social-email** — direct publishing to social/email (alternative to webhook-based distribution)
|