Skip to content

Contact Form

Availability: Free + Pro. When Pro’s Lead Forms feature is enabled, it replaces this Free contact form.

A “Contact owner” form on every listing detail page. Visitors send a private message to the listing owner; the owner gets an email; no personally-identifying data is stored on the site. Honeypot + Akismet + per-IP and per-listing rate limits in front of every submission - and when Pro’s Lead Forms feature is on, this Free surface automatically stands down so the two never render together.

Contact Form - Free Contact owner form on listing detail, with name + email + message fields

A minimal contact-owner surface for sites that don’t need full Pro lead capture:

  • Renders inline on every listing detail page (after the fields, before reviews) - no shortcode or block placement required.
  • Three required inputs: name, email, message. Plus a hidden honeypot field bots can’t resist filling.
  • Submits to POST /listora/v1/listings/{id}/contact-form with a per-listing nonce.
  • Anti-spam pipeline runs before any email is dispatched: honeypot rejection, keyword blacklist + URL density + Akismet, per-IP rate limit (3 messages per hour per listing), per-listing daily cap (default 20 - configurable via wb_listora_contact_form_per_listing_daily_cap filter).
  • Owner receives a plain-text email at their WordPress account email. Reply-To is set to the sender so a one-click reply goes straight back to the visitor - without exposing the owner’s email to the sender on the page.
  • Self-suppresses for the listing owner viewing their own page (no “contact yourself” affordance).
  • Coupling rule: when Pro’s lead_form feature toggle is ON, should_render() returns false and the Free form hides - Pro’s analytics-enriched lead form takes over with the same UX shape. Set the wb_listora_render_contact_form filter to true to force the Free form on top of Pro (rarely useful).
  1. Activate WB Listora - the contact form is on by default.
  2. Confirm your site’s outgoing email works. Try Settings → Notifications → Send Test Email with the “New listing submitted” template - if that arrives, the contact form’s wp_mail() will too.
  3. Tune the per-listing daily cap if needed: 20 is right for most directories. Reduce for low-traffic high-value listings, raise for high-volume vendors.
  4. Listing owners get messages at their profile email (WordPress account email). Encourage them to keep that current.
  1. Open any listing detail page.
  2. Scroll past the fields tab to Contact owner.
  3. Enter your name, your email, and a message of any length.
  4. Submit. The page shows “Your message has been sent to the listing owner.” inline.
  5. The owner replies directly to your email address - replies do NOT route back through the site.
  1. New messages arrive at the email address on your WP profile.
  2. Subject format: New message from {sender} about {your listing title}.
  3. Hit reply in your mail client - your reply goes straight to the visitor’s email (we set Reply-To).
  4. The site itself never stores the visitor’s name / email / message text. If you need a record, save the email in your mail archive.

The form runs every submission through the same anti-spam pipeline as listings, reviews, and claims:

Layer What it catches Configurable
Honeypot (hp field) Bots that fill every input. Silent reject - bots think they won. (no setting - built in)
Per-IP rate limit 3 messages per hour per listing per IP. Returns HTTP 429. (no setting - built in)
Per-listing daily cap 20 messages per listing per day across all IPs. Returns HTTP 429. wb_listora_contact_form_per_listing_daily_cap filter
Keyword blacklist Banned words from Settings → Security → Banned Words. Settings → Security
URL density cap Submissions over the per-event URL limit. Settings → Security
Akismet Spam content check via the Akismet API. Falls open on outage. Akismet plugin

See Spam Protection for the layered defence and Rate Limiting for the per-IP windows.

Setting Default Where
Per-listing daily cap 20 wb_listora_contact_form_per_listing_daily_cap filter
Per-IP cap 3 / hour / listing (no setting - built in)
Email subject template New message from %s about %s (translatable string)
Reply-To header Sender’s email (filterable via wb_listora_contact_form_email_headers)
Render gate On when Pro lead_form is OFF wb_listora_render_contact_form filter
// Raise the per-listing daily cap for verified listings.
add_filter( 'wb_listora_contact_form_per_listing_daily_cap', function ( $cap, $listing_id ) {
if ( wb_listora_is_verified( $listing_id ) ) {
return 50;
}
return $cap;
}, 10, 2 );
// Add a BCC for compliance archiving.
add_filter( 'wb_listora_contact_form_email_headers', function ( $headers, $post ) {
$headers[] = 'Bcc: compliance@example.com';
return $headers;
}, 10, 2 );
// Force the Free form to render even when Pro's lead form is active.
add_filter( 'wb_listora_render_contact_form', '__return_true' );

After every successful send, do_action( 'wb_listora_after_contact_form_submit', $listing_id, $context, $request ) fires - Pro’s Audit Log + Analytics features listen here to record the event.

Scenario What renders
Free only Free contact form (this page)
Pro active, lead_form toggle ON (default) Pro Lead Forms - analytics-enriched, custom fields, integrations
Pro active, lead_form toggle OFF Free contact form (this page)
Pro active, lead_form ON, filter override Both render (use carefully)
  • Lead Forms (Pro) - analytics-enriched replacement with custom fields, source attribution, integrations.
  • Spam Protection - the multi-layer defence the contact form runs through.
  • Rate Limiting - per-IP sliding window windows on every write endpoint.
  • Email Templates - message template customization.
  • REST API - POST /listora/v1/listings/{id}/contact-form endpoint reference.