Documentation · Technical Documentation

Search Alerts Technical Notes

This document describes the Search Agent / Smart Stock Alerts feature: how visitors subscribe to saved searches, how the double-opt-in flow works, where subscriptions are stored and how the matching engine is triggered after each import.

When to use this document

Read this document if you need to:

  • Diagnose missing or duplicated subscription confirmation emails.
  • Understand how matching is performed and which criteria are supported.
  • Plan a database backup or migration that includes the subscription table.
  • Audit privacy and data-retention behaviour around saved searches.

Overview

The feature is implemented in AS24CI\Search_Agent and:

  1. Renders a subscription form (typically inside the search filter zone) that POSTs to the AJAX action as24ci_search_agent_subscribe.
  2. Validates the email and selected criteria, generates a 64-character confirmation token and stores a pending row.
  3. Sends a confirmation email containing a one-click link with the token. Clicking the link activates the subscription.
  4. On every successful vehicle import, evaluates each active subscription against the new vehicle and sends a notification email when the criteria match.
  5. Provides one-click unsubscribe links in every notification email.

A bot honeypot field (as24ci_hp_field) silently discards obvious bot submissions while returning a success response so bots are not given diagnostic information.

Database table

Subscriptions are stored in <prefix>as24ci_search_agents:

ColumnTypeNotes
idBIGINT UNSIGNED AUTO_INCREMENTPrimary key.
nameVARCHAR(255) DEFAULT ''Optional contact name.
emailVARCHAR(255) NOT NULLValidated via is_email().
criteriaTEXTJSON-encoded sanitised criteria.
tokenVARCHAR(64) NOT NULL32-byte random_bytes() hex.
frequencyVARCHAR(20) DEFAULT 'daily'Notification frequency placeholder.
statusVARCHAR(20) DEFAULT 'pending'pending, active, inactive, paused.
created_atDATETIME DEFAULT CURRENT_TIMESTAMPSubscription time.
confirmed_atDATETIME NULLSet when the visitor clicks the confirmation link.

Indexes: (status), (token). The schema version is stored in the as24ci_search_agent_db_version option and dbDelta() is applied as needed.

Supported criteria

Search_Agent::sanitize_criteria() accepts only this whitelist of keys; all other fields submitted with the form are discarded:

  • make
  • model
  • body_type
  • drive_type
  • condition
  • color
  • min_price
  • max_price
  • mileage_max
  • status

Empty values and the literal string all are treated as "no constraint" and removed from the stored criteria so the matcher does not over-filter.

At least one criterion must remain after sanitisation; otherwise the AJAX endpoint responds with HTTP 422 and an error message.

Step by step: subscription flow

  1. Visitor selects criteria in the search filter and submits their email to the search-agent form.
  2. Front-end POSTs as24ci_search_agent_subscribe with the as24ci_search_agent nonce. Failed nonces return HTTP 403.
  3. The plugin validates the email and criteria, generates a token, inserts a pending row and sends the confirmation email.
  4. Visitor clicks the link (?as24ci_sa_action=confirm&token=<token>). The init handler verifies the token length (must be 64 characters), updates the row to active and sets confirmed_at.
  5. On a successful confirmation the visitor is redirected to the home URL with ?as24ci_sa_msg=confirmed. The unsubscribe flow uses the same redirect mechanism with unsubscribed.

Step by step: matching flow

  1. The importer fires as24ci_vehicle_imported after each create or update.
  2. Search_Agent::on_vehicle_imported() runs at priority 20.
  3. Updates are skipped — only vehicles that are newly created trigger notifications, to avoid spamming subscribers when an existing vehicle changes.
  4. Active subscriptions are loaded and their criteria are evaluated against the vehicle's terms and post meta.
  5. Each match results in one notification email sent via wp_mail() containing the vehicle title, link, criteria summary and unsubscribe URL.

Configuration reference

The Search Agent feature itself is enabled or disabled via the plugin feature toggle as24ci_feature_search_agent. Email templates use plain text and are translatable. The token format is fixed (64 hex chars from random_bytes(32)).

For the full list of plugin options, see Options And Settings Storage.

Operational notes

  • The endpoint is public (wp_ajax_nopriv_* is registered) so anonymous visitors can subscribe. Authentication relies on the AJAX nonce and the honeypot.
  • Tokens are cryptographically random and stored as plain hex. Treat the table as containing personal data: name, email and the visitor's stored search criteria.
  • Updates do not trigger notifications. Re-imports of existing listings (price drop, mileage update, etc.) are intentionally silent. Verify against the current plugin version if you plan to change this behaviour.
  • The frequency column is included in the schema for future use; the current matcher sends notifications immediately on each new match.
  • The confirmation and unsubscribe endpoints are routed through ?as24ci_sa_action=... query parameters on the home URL — no custom rewrite rules are introduced.
  • The table is dropped on uninstall (independent of the *delete data on uninstall* toggle) because it holds personal data. See Uninstall And Cleanup Behavior.

Troubleshooting

  • No confirmation email received — check spam folders; then verify SMTP/mailer configuration. The plugin uses wp_mail() for all subscription messages.
  • Confirmation link reports nothing — the token was empty or not exactly 64 characters, or the row was already confirmed. The endpoint silently exits if the token is malformed; this prevents enumeration attacks.
  • **Subscriber receives no notifications even after a matching import** — confirm the vehicle was a new insert (updates do not notify), the subscription is active, and at least one criterion is restrictive enough to map to a known meta key / taxonomy term.
  • Many duplicate notifications during a re-import — should not occur because updates are filtered out, but a full re-import that recreates posts from scratch would trigger notifications. Schedule full re-imports during quiet hours and consider disabling the Search Agent toggle temporarily.
  • AJAX subscribe always returns success even with bad data — the honeypot field was triggered. Confirm the form did not inadvertently fill the hidden as24ci_hp_field input.