LTL WP Post SendGrid
The LTL WP Post SendGrid plugin (I developed under Wordie) automatically turns newly-published WordPress blog posts into SendGrid Marketing Single Sends (email campaigns).
by Wordie · github.com/neogenesis/ltl-wp-post-sendgrid · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/neogenesis/ltl-wp-post-sendgrid/archive/refs/heads/main.zipLTL WP Post SendGrid (v3.0)
Automatically turns newly-published WordPress blog posts into SendGrid Marketing Single Sends — every day at a configured time.
Developed by Wordie
What it does
The plugin runs a daily cron job at the configured Send Time. It checks for blog posts published in the past 24 hours and, for each one not yet sent, creates and schedules a SendGrid Marketing Single Send.
- Daily cron at Send Time — runs once per day using the WordPress site timezone
- Audience targeting — send to Contact Lists or Segments (choose one source)
- Batch sending — create one Single Send per selected list/segment with staggered delivery
- Email Design import — load a SendGrid Design into the email template editor
- Template variables — personalise subject lines and HTML using post data
- Sandbox Mode — test without delivering real emails
- Activity Logs — full history of success and error events per campaign
- Duplicate-send prevention — each post is tracked so it only triggers one campaign
Quick Start
1. Install & activate
Upload the plugin folder to wp-content/plugins/ltl-wp-post-sendgrid/ and activate via WordPress Admin → Plugins.
2. Configure
Go to WordPress Admin → SendGrid → Settings and complete the following:
| Step | Setting | Notes |
|---|---|---|
| 1 | API Key | Paste your SendGrid API key, then click Test Connection |
| 2 | Sender ID | Click Load Senders, then select a verified sender |
| 3 | Audience Source | Choose Send to Lists or Send to Segments |
| 4 | List IDs / Segment IDs | Click Load, then select one or more |
| 5 | Suppression Group ID | Click Load Suppression Groups and select one (or provide a Custom Unsubscribe URL) |
| 6 | Email Subject | Set subject line — supports template variables |
| 7 | Email Template | Write HTML email body — supports template variables and media |
| 8 | Send Time | Set the daily time the cron job runs (e.g. 09:00) |
3. Test
Use the Test Email section to send a preview to yourself before going live.
4. Publish a post
At the next Send Time, the plugin will pick up the post and create/schedule the campaign automatically.
Settings Reference
SendGrid Configuration
| Setting | Description | Default |
|---|---|---|
| API Key | SendGrid API key. Requires Marketing, Verified Senders, Suppressions permissions. | — |
| API Mode (Sandbox Mode) | When ON: Single Sends are created but not scheduled; test emails validate but are not delivered. | Off |
| Sender ID | Verified sender from your SendGrid account. Loaded via API. | — |
| Audience Source | lists or segments — determines which audience selector is used. |
lists |
| List IDs | Multi-select contact lists loaded from GET /v3/marketing/lists. |
— |
| Segment IDs | Multi-select segments loaded from GET /v3/marketing/segments/2.0. |
— |
| Send Time | Hour and minute (24h, e.g. 09:00) for the daily cron run. Uses WordPress site timezone. |
09:00 |
| Batch Sending | Creates one Single Send per selected list/segment instead of one combined send. | Off |
| Batch Delay (minutes) | Minutes between each batched send. Range: 15–30. Only active when Batch Sending is on. | 30 |
| Suppression Group ID | SendGrid Unsubscribe Group for compliance. Required unless Custom Unsubscribe URL is set. | — |
| Custom Unsubscribe URL | URL of the page containing [ltl_sendgrid_unsubscribe]. Alternative to Suppression Group. |
— |
Email Template
| Setting | Description |
|---|---|
| Email Subject | Subject line template. Supports {{variables}}. Default: {{post_title}}. |
| Email Design | Select a SendGrid Design and load its HTML into the template editor. Click Save Changes to persist. |
| Email Template | Full HTML email body. Visual editor with Code view. Supports variables and Media Library images. |
Template Variables
Use in Email Subject and Email Template:
| Variable | Description | Example |
|---|---|---|
{{post_title}} |
Blog post title | How to Build a Website |
{{post_excerpt}} |
Post excerpt (or first 55 words) | — |
{{post_content}} |
Full post content (HTML) | — |
{{post_permalink}} |
Post URL | https://yoursite.com/post-slug/ |
{{post_publish_date}} |
Publish date (j F Y g:i A) |
15 May 2025 9:00 AM |
{{post_categories}} |
Comma-separated categories | News, Updates |
{{post_author}} |
Author display name | Jane Smith |
{{current_year}} |
Current year | 2025 |
{{unsubscribe_link}} |
Unsubscribe URL with recipient email pre-filled | Requires Custom Unsubscribe URL to be set |
Starter template
<h1>{{post_title}}</h1>
<p><em>By {{post_author}} on {{post_publish_date}}</em></p>
<p>{{post_excerpt}}</p>
<p><a href="{{post_permalink}}">Read the full post →</a></p>
<hr />
<p style="font-size:12px;color:#666;">© {{current_year}} | <a href="{{unsubscribe_link}}">Unsubscribe</a></p>
How Campaigns Are Sent
Daily cron process
- At the configured Send Time, WordPress triggers the plugin's daily cron job
- Finds posts published in the last 24 hours that haven't triggered a campaign yet
- Creates a SendGrid Marketing Single Send via
POST /v3/marketing/singlesends - Schedules it for immediate delivery via
PUT /v3/marketing/singlesends/{id}/schedule - Marks the post with
_sendgrid_campaign_triggeredto prevent duplicate sends
Campaign naming
LTL in focus | [date] - [post title]
Capped at 100 characters total (truncated with ... if needed).
Batch sending
When Batch Sending is enabled, one Single Send is created per selected list/segment:
- First send:
now - Each subsequent:
now + (index × batch_delay_minutes) - Example (3 lists, 30-min delay): sends at now, now+30min, now+60min
- If any batch send fails, remaining sends in that batch are cancelled
Sandbox Mode
| Mode | Test email (/mail/send) |
Marketing Single Send |
|---|---|---|
| Sandbox ON | Validated, not delivered | Draft created, not scheduled |
| Sandbox OFF | Delivered normally | Created and scheduled |
Post Meta Box
On the post edit screen, the SendGrid Campaign Status sidebar box shows:
- Whether a campaign has been triggered for this post
- The SendGrid campaign ID and triggered-at timestamp
- Clear SendGrid Flag — resets the post so it can be re-sent on the next cron run
- Send Test Email — sends a preview without updating post meta
Campaign Logs
WordPress Admin → SendGrid → Logs
- Filter by Success or Error
- Click View on any row to expand the full data payload
- Clear Logs permanently deletes all log records
Unsubscribe Shortcode
The plugin provides a built-in unsubscribe form that integrates with SendGrid Suppression Groups.
Shortcode: [ltl_sendgrid_unsubscribe]
Setup:
- Create a WordPress page (e.g. "Unsubscribe")
- Add
[ltl_sendgrid_unsubscribe]to the page body - Copy the page URL → paste into Settings → Custom Unsubscribe URL
- Add
<a href="{{unsubscribe_link}}">Unsubscribe</a>to your email template
Behaviour:
- If
?ce=email@example.comis present in the URL, the email is pre-filled - On confirmation, the plugin adds the email to the configured Suppression Group via
POST /v3/asm/groups/{id}/suppressions - Publicly accessible (no login required), secured with a WordPress nonce
Troubleshooting
| Issue | Solution |
|---|---|
| "SendGrid API key not configured" | Enter your API key in Settings and click Save Changes |
| No senders in dropdown | Verify a sender in SendGrid (Settings → Sender Authentication), then click Load Senders |
| Scheduling fails — unsubscribe error | Provide a Suppression Group ID or a Custom Unsubscribe URL in Settings |
| Nothing happens after publishing | WP-Cron needs site traffic to fire. Use a real server cron for reliability (see below) |
| Post sent twice | Check if Clear SendGrid Flag was used — it resets the duplicate-send guard |
| Sandbox Mode — emails not arriving | Sandbox Mode prevents delivery by design. Uncheck it in Settings to send real emails |
| No posts found at Send Time | Posts must be in Published status. Check Send Time is set correctly |
Setting up a real server cron (recommended for production)
Add to wp-config.php:
define('DISABLE_WP_CRON', true);
Add to your server crontab:
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
Data Storage
WordPress Options
| Option | Type | Description |
|---|---|---|
ltl_sendgrid_api_key |
string | SendGrid API key |
ltl_sendgrid_sandbox_mode |
int (0/1) | Sandbox mode toggle |
ltl_sendgrid_sender_id |
string | Verified sender ID |
ltl_sendgrid_which_list |
string | lists or segments |
ltl_sendgrid_list_ids |
array | Selected contact list IDs |
ltl_sendgrid_segment_ids |
array | Selected segment IDs |
ltl_sendgrid_send_time |
string | Daily send time (HH:MM) |
ltl_sendgrid_batch_sending |
int (0/1) | Batch sending toggle |
ltl_sendgrid_batch_delay |
int | Batch delay in minutes (15–30) |
ltl_sendgrid_suppression_group_id |
int | Suppression Group ID |
ltl_sendgrid_custom_unsubscribe_url |
string | Custom unsubscribe page URL |
ltl_sendgrid_email_subject |
string | Email subject template |
ltl_sendgrid_email_design_id |
string | Selected SendGrid Design ID |
ltl_sendgrid_email_template |
string | Full HTML email template |
Post Meta
| Key | Description |
|---|---|
_sendgrid_campaign_triggered |
Boolean — marks post as sent |
_sendgrid_campaign_id |
Primary Single Send ID |
_sendgrid_campaign_ids |
JSON array of all IDs (batch mode) |
_sendgrid_campaign_triggered_at |
MySQL datetime of campaign trigger |
Database Table
{prefix}_ltl_sendgrid_logs — created on plugin activation.
| Column | Type | Description |
|---|---|---|
id |
bigint | Auto-increment primary key |
log_type |
varchar(20) | success or error |
message |
text | Human-readable event summary |
data |
longtext | JSON payload (post ID, campaign IDs, errors, etc.) |
created_at |
datetime | Timestamp of the event |
Permissions
| Action | Required Capability |
|---|---|
| Settings page, all admin AJAX actions | manage_options (Administrator) |
| Post meta box, test email from post screen, clear flag | edit_posts (Editor and above) |
| Unsubscribe form (frontend) | Public — no login required |
Changelog
3.0
- Daily cron at configurable Send Time replaces the previous publish-triggered approach
- Send Time field — hour and minute using the WordPress site timezone
- Replaced Delay Sending with Send Time
- Posts published in the past 24 hours are picked up; campaigns send immediately
2.0 beta
- Unified Email Template field (replaces legacy header/body/footer fields)
- Audience Source toggle — Contact Lists vs Segments
- Segment loading with multi-select
- Batch sending per list/segment with configurable delay
- Email Design selection with load-into-template
- Campaign title capped to 100 characters