Ultimate Classified Listings – Classifieds, Directory & Marketplace

Opis

Ultimate Classified Listings is a responsive classifieds and directory plugin for WordPress. It ships nice, clean templates and built-in features like unlimited custom fields, gallery sliders + grids, advanced AJAX search and Google Maps or OpenStreetMap support out of the box.

It’s also a full listing management system: register sellers, approve submissions, manage seller profiles, and run your own classifieds, jobs, real-estate, services or community marketplace.

Why Ultimate Classified Listings

  • Free where the leaders paywall — maps, AJAX search, frontend submission and custom fields are all free.
  • Stable and secure — A comprehensive security hardening pass: CSRF nonces on every AJAX endpoint, plaintext passwords no longer stored in options, email header injection closed, and rate limiting on auth flows.
  • Theme-friendly — full template override system, works with any WordPress theme.
  • Multilingual ready — WPML and Polylang aware.
  • Developer friendly — 40+ hooks and filters, REST API support on the listing CPT.

Core Features

  • Frontend listing submission with custom field sections
  • Unlimited custom fields and field sections (drag-and-drop builder)
  • Categories and tags with custom icons / images
  • Gallery sliders and image grids
  • AJAX-powered search with filters, price range and sort
  • Google Maps or OpenStreetMap (Leaflet) with location markers
  • Seller dashboard: add / edit / delete listings, profile management
  • Two seller-registration modes: auto-approve or manual approval
  • Two submission modes: publish immediately or pending review
  • Listing comparison
  • Contact-seller form with reCAPTCHA + email-injection protection
  • Compare and share listings
  • Full theme template overrides under /your-theme/ucl/...

Quick Links

Zrzuty ekranu

Instalacja

  1. Navigate to the WordPress Dashboard -> Plugins -> Add New
  2. Search for the Ultimate Classified Listings
  3. Install and Activate
  4. Now configure the settings from the Ultimate Classified Listings -> Settings

Najczęściej zadawane pytania

Is this plugin free?

Yes. The core plugin is free, including maps, AJAX search, frontend submission, and custom fields.

Does it work with Elementor, Gutenberg or Divi?

The plugin uses shortcodes that work in any builder. Native Gutenberg blocks are on the v3.0 roadmap.

Do I need a Google Maps API key?

No. The plugin ships OpenStreetMap via Leaflet by default. If you prefer Google Maps, you can add your API key in Settings.

Can I let users pay to post listings?

Built-in payment gateways are on the v3.0 roadmap. In v2.x you can use Settings Submission Mode to require admin approval before listings are published.

How are seller passwords stored?

As of 2.0, passwords are no longer stored in plain text in wp_options. Newly registered users that require manual approval have their password hashed before storage. Legacy entries from prior versions will receive a one-time password reset email when approved.

How does the plugin protect against CSRF?

Every AJAX endpoint requires a nonce verified by check_ajax_referer(). Public requests use a dedicated public nonce and admin requests use a separate admin nonce, both rotated by WordPress.

I’m migrating from another plugin. Is there a migration tool?

Migration tools from Directorist, WP Adverts and Classified Listing are on the v3.x roadmap. For now you can use WP All Import/Export/

Recenzje

2022-10-15 1 odpowiedź
I like the aesthetics and the speed of responsiveness in this script. The developer brings in a considerable experience in similar app functionality which translates to having a very mature script from its first version.
2022-08-12 1 odpowiedź
I build a lot of listing websites by using many themes and plugins but this is the best solution I found on the internet so far. It’s easy to use backend and Ajax loading with map integration everything works smooth and fast. recommended this plugin to anyone who tries to create a listing website.
Przeczytaj 2 recenzje

Kontrybutorzy i deweloperzy

„Ultimate Classified Listings – Classifieds, Directory & Marketplace” jest oprogramowaniem open source. Poniższe osoby miały wkład w rozwój wtyczki.

Zaangażowani

Rejestr zmian

2.0 – 14 June 2026

  • Bug fix: When the archive/search-results top bar was rendered (via [uclwp_search_results top_bar="enable"] or anywhere the uclwp_archive_topbar action fires) and a visitor changed the sort dropdown, the resulting URL kept only sort_by and layout and dropped every other active query arg — keywords, price range, custom-field filters, etc. The top bar now re-emits every other $_GET value as a hidden input inside the form (using PHP bracket notation for nested sub-arrays like regular_price[min]), so the sort round-trip preserves the active filter set. The grid/list switcher anchors already used add_query_arg() and were unaffected.
  • Added: New helper uclwp_flatten_query_args() that flattens nested arrays into name[sub][sub] / value pairs suitable for hidden form inputs. Reusable from any template that needs to pass current GET state through a <form method="GET">.

1.16.0

  • Feature: Two new single-listing styles. Pick one in Settings Templates Settings Single Listing Style. Style 1 (Classic, default) is the existing look. Style 2 (Card Stack) renders each section as a raised card with a coloured left rail and a chip-style heading — e-commerce / property-listing feel. Style 3 (Minimal) drops the card chrome entirely and separates sections with thin top dividers. Implemented as a body class (ucl-listing-style-1/2/3) added on single-listing pages; templates are unchanged so all theme overrides keep working.
  • Feature: Price quick-pick chips are now editable from the admin. New „Price Quick-Pick Presets” textarea in Settings Search Settings (right after Total Listings) — one numeric preset per line; each becomes a „Up to {price}” chip under the price range control in search styles 2 and 3. Leave blank to hide the chips entirely. Still filterable in code via uclwp_search_price_chips.
  • Feature: [uclwp_search_results] now supports a top_bar="enable" attribute (default disable) that adds the same sort + grid/list switcher the [uclwp_listings] shortcode renders.
  • Feature: Per-listing map zoom level is now saved. The admin metabox map writes the user-chosen zoom into a hidden ucl_listing_zoom input (Leaflet zoomend and Google zoom_changed events both wired up); both the admin metabox save path and the frontend create/edit handler persist it; the single-listing template reads it back and the map opens at exactly that zoom on the frontend.
  • Improvement: Search style 2 polish — reduced cell min-height from 46px to 38px, button is now a properly sized pill (not a tall circle), inputs no longer have huge top/bottom padding. New columns shortcode attribute (1–6, default 4) controls how many secondary-field cells appear per row via CSS grid. Mobile collapses to 2 columns at ≤768px and 1 column at ≤480px.
  • Bug fix: Card image aspect ratio (Settings Listings Card Image Aspect Ratio) was not being applied. The CSS selector keyed off [style*="--ucl-card-image-ratio"], which never matched because the variable is emitted via an inline <style> tag, not the element’s style attribute. The aspect-ratio rule now applies directly to .uclwp-grid-box-wrap .uclwp-image and .uclwp-list-box-wrap .uclwp-image, so all four card styles honour the chosen ratio.

1.15.0

  • Feature: Two new search-form styles, selectable via [uclwp_search_form style="2"] and [uclwp_search_form style="3"].
    • Style 2 — Bar: Compact horizontal pill bar with rounded inputs, designed to sit above an archive grid. Trulia/Zillow feel.
    • Style 3 — Hero: Tall hero panel with a prominent keyword box, neat secondary-field grid below, and a final CTA row with a „Clear filters” link. Designed to anchor landing or category-archive pages. Configurable heading + sub-heading via the new search_form_heading / search_form_subheading settings.
  • Feature: New uclwp_render_price_range_search() helper renders a modern two-input price control with the currency symbol affixed inside each input, plus optional quick-pick chips („Up to $100”, „Up to $500”, etc.). Used by styles 2 and 3. Preset chip values are filterable via uclwp_search_price_chips.
  • Improvement: Equal-height listing cards. Cards within the same row now stretch to match the tallest neighbour and push price/CTA footer rows to the bottom, so grids look tidy even when titles/excerpts vary in length. Scoped to .ucl-display-listings so single-listing sidebars and the compare box are unaffected.
  • Bug fix: [uclwp_categories] (and the underlying render_category_image()) no longer renders the saved Bootstrap-icon class. The previous wrapper produced class="bi bi-{bi bi-house}", an invalid class that resolved to nothing. Output is now class="bi bi-house" (or the admin-set value). Categories with a saved icon will start rendering it immediately on update.
  • Bug fix: Long seller email addresses were overflowing the contact box in the single-listing sidebar. The <li> rows now apply overflow: hidden; text-overflow: ellipsis; white-space: nowrap; and pick up the missing right padding so the email truncates inside the bordered chip.

1.14.2

  • Bug fix: When creating a new listing in wp-admin, Leaflet threw Invalid LatLng object: (undefined, undefined) and the map widget failed to render. Root cause was the v1.14.1 admin-enqueue fix, which preloaded the frontend single-listing map script (assets/js/location.js) on the post-edit screen. That script expects a different localize payload (ucl_location_settings.latitude/longitude) than the metabox renderer provides (ucl_map_settings.def_lat/def_long), so its values came up undefined. The redundant enqueue has been removed — the location field renderer enqueues the correct script (assets/fields/location.js) on its own when the section actually renders.
  • Bug fix: Belt-and-braces hardening of the location renderer so that even if a stored listing has empty latitude/longitude meta the JS still receives a numeric default (US geographic centre, 37.0902 / -95.7129). The previous longitude default lost its negative sign so the placeholder pin showed up in central Asia instead of Kansas.
  • Bug fix: Control.Geocoder.js now declares ucl-leaflet-js as a dependency so the geocoder loads after Leaflet on the post-edit screen.

1.14.1

  • Bug fix: The Listing Information metabox on the wp-admin post-edit screen (post.php / post-new.php for the uclwp_listing CPT) was rendering without Bootstrap CSS, the icon font, the iconpicker JS, the media uploader, or the map widget. The load_admin_scripts() enqueue gate previously matched only the plugin’s own subpages (slug contained „uclwp”); it now also enqueues all required assets when the current admin screen’s post_type is uclwp_listing. Bootstrap stays scoped to .uclwp-bs-wrapper so it does not affect the surrounding wp-admin UI.

1.14.0

Final WordPress.org Plugin Check pass — clears all reported errors for plugin-directory submission.

  • Plugin name: Renamed to „Ultimate Classified Listings – Classifieds, Directory & Marketplace” so the readme title matches the plugin header and the word „Plugin” (a restricted term) is no longer part of the displayed name.
  • Tested up to: bumped to 7.0 to match the current WordPress release as required by .org.
  • Escaping: Wrapped the dynamic CSS variable block emitted by assets/css/styles.php through wp_strip_all_tags() after each value is individually escaped via esc_attr(), with phpcs:ignore annotations explaining why the final concatenation is safe.
  • Escaping: paginate_links() output in render_pagination() now passes through wp_kses_post() before echoing.
  • i18n: Added /* translators: %s ... */ comments above two printf( esc_html__( ... ), ... ) calls in the setup-wizard „next steps” panel that were missing them.
  • Sanitization: Added sanitize_text_field( wp_unslash( ... ) ) wrappers around $_REQUEST['listing_id'] reads in class-shortcodes.php delete_listing, class-email.php contact_seller, class-favorites.php ajax_toggle, and shortcodes/dashboard/edit.php. The values are still validated through uclwp_validate_listing_id().
  • Sanitization: $_SERVER['REQUEST_URI'] used to build the favorites login-redirect URL now passes through esc_url_raw( wp_unslash( ... ) ) before home_url().
  • Sanitization: Recursive array inputs ($_POST['uclwp_data'], $_REQUEST['sections'], $_REQUEST['fields']) now have phpcs:ignore annotations documenting that each leaf is sanitized further down. The actual per-leaf sanitization was already in place.
  • Sanitization: Login/register password reads carry phpcs:ignore annotations explaining why passwords must not be passed through sanitize_text_field() (would strip control characters needed for hash comparison).
  • File uploads in seller registration carry phpcs:ignore annotations pointing to the nonce check at the top of the handler.

1.13.0

Second WordPress.org Plugin Check pass — addresses the warnings flagged by the official PCP tool that the manual sanitization audit missed.

  • Plugin Check: Added defined( 'ABSPATH' ) || exit; guard to 32 files that didn’t have one, including all template files, shortcode partials, admin subviews, the inc/arrays/ data files and assets/css/styles.php.
  • Plugin Check: Replaced all json_encode( $resp ) AJAX response calls with wp_send_json( $resp ) so character encoding follows WP’s UTF-8 conventions and the response is properly closed via wp_die().
  • Plugin Check: Replaced remaining non-AJAX json_encode() calls (Slick / image-grid data-attributes) with wp_json_encode().
  • Plugin Check: Added explicit timeout argument (10 s) to every wp_remote_post() call.
  • Plugin Check: Added rel="noopener noreferrer" to every target="_blank" link in the admin settings help text, the post-update messages, and the setup-wizard „next steps” panel.
  • Plugin Check: Removed load_plugin_textdomain() — WordPress 4.6+ loads translations automatically for plugins hosted on .org and the call is now flagged as discouraged.
  • Plugin Check: Replaced bare die(); / die(0); with wp_die(); in AJAX handlers.
  • Plugin Check: Added missing version arguments to every wp_enqueue_style / wp_enqueue_script call (used UCLWP_VERSION for bundled assets and null for third-party CDN scripts whose URL already carries a version key).
  • Plugin Check: Renamed three filters that were missing the plugin prefix: no_results_message uclwp_no_results_message, seller_contact_email_message uclwp_seller_contact_email_message, raw_uclwp_price uclwp_raw_price, formatted_uclwp_price uclwp_formatted_price.
  • Plugin Check: Removed nested esc_attr( sanitize_text_field( … ) ) double-escape pattern in the search-form field renderer; the value is now sanitized once on input and the existing esc_attr() at output point handles HTML-attribute escaping.
  • Plugin Check: Google-Maps script URL now built via add_query_arg() instead of string concatenation, and routed through HTTPS unconditionally.
  • Plugin Check: Direct $wpdb->update() call in seller-approve flow now has type-specifier arrays for $where and $data and a justification comment explaining why the WP user-API helpers can’t be used (the password is already hashed).

1.12.0

This release is a full sanitization + escaping pass for WordPress.org plugin review compliance. No behaviour changes; every output path is now explicitly escaped and every input path is unslash + sanitized.

  • Sanitization: All $_GET / $_POST / $_REQUEST access across the plugin now runs through wp_unslash() before sanitization, matching WordPress core conventions and WPCS requirements.
  • Escaping: Replaced esc_attr_e() / esc_attr__() with the correct esc_html_e() / esc_html__() everywhere the output is HTML body content (labels, table cells, headings, paragraph text). Attribute-context calls (placeholder="", title="", value="", data-*="") remain esc_attr_e().
  • Escaping: Replaced esc_attr() with esc_html() on user-controlled body text — listing titles, seller names, emails, phone numbers, category names, etc.
  • Escaping: Textarea content now uses esc_textarea() instead of esc_attr().
  • Bugfix: compare-box.php printed nothing for compare table column headers due to esc_attr( $label ) (which returns instead of echoing). Now properly echo esc_html( $label ).
  • Hardening: Removed the second hardcoded reCAPTCHA fallback key in templates/sidebar/default.php. CAPTCHA now fails closed when not configured.
  • Hardening: gdpr_message setting in the contact-seller form is now output via wp_kses_post() so admins can include safe HTML formatting (was esc_attr() which broke the HTML).
  • Hardening: Search query builder (uclwp_get_search_query) sanitizes all dynamic orderby, meta_key, tag, and range inputs and validates against an allow-list before passing to WP_Query.
  • Hardening: HTML emails (contact-seller) now esc_html() user-controlled fields (client name, email, phone, message, listing title) before HTML interpolation.
  • Hardening: Compare AJAX listing IDs cast through absint(); meta_key segments through sanitize_key().
  • Hardening: class-shortcodes::update_profile casts and unslashes every $_REQUEST field.
  • Hardening: Term-meta image/icon callbacks (save_category_image, updated_category_image) now check current_user_can('manage_categories') and wp_unslash() the inputs (core verifies the nonce upstream on the term-edit screen).
  • Hardening: Dashboard „My Listings” search query reads $_GET['uclwp_status'] through an enum allow-list (publish, pending, draft, future, any).
  • Compatibility: selected() and selected( $a, $b ) used in place of inline ($a == $b) ? 'selected' : '' ternaries where the markup allowed it.
  • Compatibility: (int) $cat->count and (int) count_user_posts(...) casts in page-sellers.php and other admin lists in place of esc_attr() on integers.

1.11.0

  • Feature: Modern field rendering. Custom fields on single-listing pages now render as icon + label + value cards by default, using each field’s saved icon (from the Fields Builder). Two additional display modes are available — „List” (definition-list rows) and „Inline” (compact icon pills). Choose via Settings Listings Field Display on Single Listing Pages.
  • Feature: Card meta strip redesigned as inline icon pills with the field’s icon, replacing the previous flat title-pipe-value rows. Customize which fields appear via the new Card Meta Fields setting (comma-separated keys).
  • Feature: Checkbox / features fields now render as accent-coloured chips with check icons, instead of plain bulleted text.
  • Feature: Favorites (save listings). Adds a heart button to every listing card. Saved listings are stored per-user and viewable via the new „Saved Listings” item in the seller dashboard or the [uclwp_favorites] shortcode. Toggle the feature in Settings Listings Favorites.
  • Feature: Dark mode. Five options — Off, Auto (follow OS), Toggle (manual button in top-bar), Auto + Toggle, and Force. Six dark-mode colour overrides for surface, card background, card border, heading, body and muted text.
  • Improvement: Field-display helpers now resolve safely when a value is empty so cards never render orphan labels.
  • Improvement: uclwp_listing_action_buttons filter added so add-ons can inject extra card buttons without forking templates.
  • Improvement: uclwp_dashboard_allowed_pages filter added.

1.10.0

  • Feature: Three new listing card styles. Style 2 — Minimal (flat, bordered, generous whitespace), Style 3 — Bold Overlay (full-bleed image with gradient and meta overlaid), Style 4 — Compact / Magazine (dense layout with prominent CTA). Each ships with both a grid and a list variant. Switch globally from Listings Listing Card Style, or per-shortcode via [uclwp_listings style="3"].
  • Feature: 14 new colour controls under Colors and CSS — Primary, Primary Hover, Secondary, Accent, Heading, Body Text, Muted Text, Card Background, Card Border, Surface, Price, Badge Background, Badge Text, Button Background/Text/Hover. Each is emitted as a CSS custom property on .uclwp-bs-wrapper so themes and custom CSS can override them too.
  • Feature: Card Corner Radius setting (0–64px).
  • Feature: Card Image Aspect Ratio setting (Original / 4:3 / 16:9 / 1:1 / 3:4) — useful when seller-uploaded images vary in dimensions.
  • Compat: Existing installs see no visual change. The legacy two-colour palette (Primary / Secondary Color) is preserved and used as the fallback when the new individual settings are blank.

1.9.0

  • Feature: Setup wizard. A short, dismissible welcome screen guides new installs through site type, page creation (Listings, Search, Categories, Seller Dashboard), currency, map provider and submission workflow. Triggered on activation and surfaced via a one-line admin notice until completed.
  • Feature: Auto-create essential pages with the correct shortcodes pre-inserted.
  • Feature: Polite, non-blocking „leave a review” prompt. Appears only after 7 days + 3 published listings, with Remind Later (14 days) and Permanent Dismiss options.
  • Improvement: Admin classes now load only in is_admin() context to reduce frontend overhead.

1.8.0

This is a major security hardening release. All sites should update.

  • Security: Added CSRF nonce verification to every public AJAX endpoint (uclwp_search_listing, uclwp_seller_login, uclwp_seller_register, uclwp_create_listing_frontend, uclwp_delete_listing, uclwp_contact_seller, uclwp_compare_listings).
  • Security: Added CSRF nonce verification to admin AJAX endpoints (uclwp_save_field_sections, uclwp_save_custom_fields, uclwp_reset_custom_fields, wcp_uclwp_save_settings, ucl_deny_seller, ucl_approve_seller).
  • Security: Pending-seller passwords are no longer stored in plaintext in wp_options. New registrations store only a salted hash; legacy entries are routed through the standard password-reset flow on approval.
  • Security: Fixed email header injection in the contact-seller form. From: header now sanitized via a dedicated helper, newlines stripped from name, Reply-To added, Cc recipients individually validated.
  • Security: Removed the hardcoded reCAPTCHA secret-key fallback. CAPTCHA verification now fails closed when not configured.
  • Security: Replaced unvalidated $_SERVER['REMOTE_ADDR'] use with filter_var(... FILTER_VALIDATE_IP).
  • Security: Listing IDs in delete and edit flows are now validated against the uclwp_listing post type and authorized via current_user_can('edit_post'|'delete_post', $id) instead of manual ownership checks.
  • Security: Pending-seller userindex is cast to integer and validated against existing keys before use.
  • Security: Permalink-settings save path now requires the core update-permalink nonce.
  • Security: Added transient-based rate limiting on login, registration and contact-seller endpoints.
  • Security: Asset URLs now include UCLWP_VERSION for cache busting after security updates.
  • Bumped minimum WordPress to 6.0 and minimum PHP to 7.4.
  • License header reconciled to GPLv2-or-later.

1.7

  • Bug Fixed: Security related issues

1.6

  • Bug Fixed: Security related issues

1.5

  • Bug Fixed: Security issues fixes, notified by Wordfence

1.4

  • Feature Added: Ability to choose category from the frontend
  • Feature Added: Ability to assign tags from the frontend
  • Bug Fixed: Empty categories are not displaying
  • Bug Fixed: Security issues fixes, notified by WPScan Team

1.3

  • Bug Fixed: Security issues fixes, notified by WPScan Team

1.2

  • Bug Fixed: Iframes not saving from frontend

1.1

  • Feature Added: Iframes support in the shortcode field

1.0.0

  • Initial Release