ThemeXpert Search Sync
Synchronizes WordPress posts with an external Meilisearch index and processes secure incoming webhooks.
by Mahbubur Rahman · github.com/mahbub-diu/action-schedular-
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/mahbub-diu/action-schedular-/archive/refs/heads/master.zipthemexpert-interview-task
A WordPress plugin that synchronizes a custom Docs post type with an external Meilisearch index and securely processes incoming webhooks from an external SaaS application.
Features
- Registers a custom Docs post type.
- Synchronizes published and updated Docs posts to Meilisearch.
- Uses Action Scheduler to process indexing and deletion requests asynchronously.
- Normalizes document data before indexing.
- Removes HTML tags and WordPress shortcodes from post content.
- Exposes a secure REST API webhook endpoint.
- Verifies incoming webhook requests using HMAC SHA-256 signatures.
- Queues delete requests received from the webhook for background processing.
Plugin Structure
tx-search-sync.php
README.md
│
├── vendor/
│ └── action-scheduler/
│
└── includes/
├── Plugin.php
├── ApiClient.php
├── PostType.php
├── Queue.php
├── SyncService.php
└── WebhookController.php
Architecture Overview
| File | Responsibility |
|---|---|
tx-search-sync.php |
Plugin bootstrap file that loads dependencies and starts the plugin. |
Plugin.php |
Initializes plugin services and registers WordPress hooks. |
PostType.php |
Registers the Docs custom post type. |
SyncService.php |
Normalizes post data and queues indexing jobs. |
Queue.php |
Registers and processes Action Scheduler background jobs. |
ApiClient.php |
Sends requests to the Meilisearch API. |
WebhookController.php |
Registers the REST endpoint, validates webhook signatures, and queues deletion requests. |
Background Queue
The plugin uses Action Scheduler to process all communication with the external search API asynchronously.
Why?
Sending HTTP requests while WordPress is saving a post can slow down the editor and may fail if the external service is temporarily unavailable.
Instead, the plugin queues work and processes it in the background.
Outgoing Sync
- A Docs post is published or updated.
- The post data is normalized.
- HTML tags and WordPress shortcodes are removed.
- A background job is queued.
- Action Scheduler sends the document to Meilisearch.
Incoming Webhook
- A webhook request is received.
- The HMAC SHA-256 signature is verified.
- If valid and the action is
delete_indexed_post, a background deletion job is queued. - Action Scheduler deletes the document from Meilisearch.
This approach keeps the WordPress request lifecycle fast and non-blocking.
Normalized Document Format
Before dispatching, each document is converted into the following JSON structure:
{
"id": 42,
"title": "Getting Started",
"clean_content": "Install the CLI and run the init command to scaffold a project.",
"author_name": "Jane Doe"
}
The clean_content field is generated by stripping HTML tags and WordPress shortcodes.
Search API
Base URL
https://search.thrivedesk.xyz
Authentication
Authorization: Bearer <API_KEY>
Add / Update Document
POST /indexes/docs/documents
The request body is sent as a JSON array, even when indexing a single document, as required by the Meilisearch API.
Delete Document
DELETE /indexes/docs/documents/{id}
Secure Webhook
Endpoint
POST /wp-json/myapp/v1/webhook
Signature Verification
Every request must include an X-Signature-Hash header.
The plugin verifies the HMAC SHA-256 signature against the raw request body using the shared secret before processing the request.
Responses:
- 401 Unauthorized — Signature is missing or invalid.
- 202 Accepted — Signature is valid and the deletion task has been queued.
Supported Payload
{
"action": "delete_indexed_post",
"post_id": 42
}
Testing the Webhook
Example:
SECRET='whsec_7Qm2Kx9Lp4Rv8Tn3Wj6Zc1Yb5Hd0Fg'
BODY='{"action":"delete_indexed_post","post_id":42}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.*= //')
curl -i \
-X POST http://localhost/themexpert/wp-json/myapp/v1/webhook \
-H "Content-Type: application/json" \
-H "X-Signature-Hash: $SIG" \
--data-raw "$BODY"
Expected responses:
- 401 Unauthorized — Missing or invalid signature.
- 202 Accepted — Valid signature and the deletion request has been queued.
Requirements
- WordPress 6.x+
- PHP 8.1+
- Action Scheduler (bundled with the plugin)
AI Disclosure
The following AI tool was used during development:
- ChatGPT (OpenAI)
ChatGPT was used to assist with code explanations, debugging, documentation, and general implementation guidance. The plugin architecture, implementation strategy, design decisions, and final code were independently designed and implemented by the author.
Author
Mahbubur Rahman