Major feature: auto-publish to Google Business Profile via the official API. Connect your Google account once via the built-in OAuth 2.0 wizard, pick your GBP location, flip the toggle on. Queued posts publish themselves at their scheduled slot — no more manual paste-and-click.
Per-install OAuth credentials: each install uses its own Google Cloud project. The plugin never embeds a shared client. Client Secret + refresh token stored encrypted at rest (AES-256-CBC, key derived from AUTH_KEY).
4-step in-product setup wizard with copy-able redirect URI, step-by-step Google Cloud Console screenshots, and live connection status.
New Settings panel: connection status card, location picker, auto-publish toggle, change-location and disconnect actions.
New queue states: Failed (red pill, persisted Google API error message, one-click Retry).
New per-row actions: Publish now (for ready items) and Retry publish (for failed items) when auto-publish is enabled.
New REST endpoints (all manage_options-gated except the OAuth callback which uses a state-nonce): /oauth/credentials, /oauth/start, /oauth/callback, /oauth/disconnect, /oauth/status, /locations, /location/select, /auto-publish, /publish/{id}.
Schema migration to v2: queue table adds google_post_id and error_message columns. Runs automatically on update via dbDelta().
Cron tick now publishes due items in batches of 5 (soft cap) so a transient API failure doesn’t fire 100 calls back-to-back.
Hardened OAuth callback: rejects requests with missing or invalid state nonces, surfaces Google’s ?error=access_denied to the admin in a styled HTML error page instead of a confusing “missing parameter” message.
Semi-manual mode preserved as a fallback. Existing installs that haven’t connected Google see the queue and dashboard widget exactly as before.
1.1.1
Branding: plugin renamed from “GBPoster for Google Business Profile” to “GMB Poster” (display name only). The plugin slug, folder name, class names, database table, and option keys are unchanged — existing installs upgrade silently with no data migration.
Updated banner artwork to match the new name.
1.1.0
Feature: “Connect to Google Business Profile” wizard. New button + status pill on the Settings screen replaces the bare URL text field. Opens a 2-step modal: click to open business.google.com in a new tab, paste the URL back (via clipboard or manual paste). Backend validates the URL pattern, strips tracking parameters, and stores the canonical URL. Power users can still edit the URL directly via the toggle.
Feature: new REST endpoint POST /gbposter/v1/connect/save (manage_options only).
Polish: connection status pill on Settings shows the GBP location ID when one is detected in the URL.
1.0.7
Compatibility: tested with WordPress 7.0; bumped Tested up to: 7.0. No code changes — full Playwright suite (16/16) and Plugin Check pass on a clean WP 7 install.
1.0.6
Security: REST API permission_callbacks now perform per-resource checks. All item-by-id endpoints (/item/{id}, /item/{id}/prepared, /posted, /skipped, /reschedule) verify the current user can edit the related WP post (current_user_can(‘edit_post’, $post_id)), not just edit_posts in general. /enqueue/{post_id} likewise. /next now walks ready items and only returns the first one the user has access to.
1.0.5
REST: /gbposter/v1/item/{id} and /gbposter/v1/next responses now include prepared_at and posted_at timestamps. Helps client code (and end-to-end tests) verify queue-item lifecycle without a second DB lookup.
1.0.4
Fix: corrected the Plugin URI to point to a working URL (https://defyn.com.au/).
Fix: text domain renamed from “gbposter” to “gbposter-for-google-business-profile” to match the plugin slug, so translations register correctly via the WordPress.org translation tools.
Security: $_POST input on the settings save handler is now sanitized at the input boundary with map_deep( …, ‘sanitize_text_field’ ) before per-field re-sanitization in GBPoster_Settings::sanitize().
Security: queue list query() rewritten so the ORDER BY column name uses the %i identifier placeholder in $wpdb->prepare(); the order direction is interpolated only from a strict 2-value (ASC|DESC) allowlist.
1.0.3
Compliance: tightened phpcs:ignore annotations on the queue list-query (NotPrepared rule).
Compliance: prefixed all top-level variables in uninstall.php.
1.0.2
Compliance: rewrote all custom-table queries to use $wpdb->prepare() with %i identifier placeholder.
Compliance: removed unnecessary load_plugin_textdomain() (WordPress auto-loads since 4.6).
Compliance: removed Domain Path header (no /languages folder shipped).
Compliance: bumped Tested up to: 6.9, Requires at least: 6.2 (for %i support).
Polish: added translators comment for sprintf placeholder.
1.0.1
Fix: settings save now redirects back to the Settings screen (was landing on admin-post.php).
Fix: in cooldown mode, the first queued item is now scheduled for “now” rather than waiting one cooldown interval.
Fix: editor “Add to GBP queue” button now uses a REST endpoint (avoids the nested-form HTML issue inside the post editor).
1.0.0
Initial release.
Custom queue table with five-status workflow.
Time-of-day slot scheduling and cooldown mode.
Auto-queue on publish with post-type and category filters.
Dashboard widget and admin Queue screen with the “Prepare next” one-click handoff.
Per-post opt-out meta box.
REST API endpoints for the handoff flow (require edit_posts capability and a valid REST nonce).