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
Instalacja
- Navigate to the WordPress Dashboard -> Plugins -> Add New
- Search for the Ultimate Classified Listings
- Install and Activate
- 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
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żowaniInteresuje cię rozwój wtyczki?
Przeglądaj kod, sprawdź repozytorium SVN lub czytaj dziennik rozwoju przez RSS.
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 theuclwp_archive_topbaraction fires) and a visitor changed the sort dropdown, the resulting URL kept onlysort_byandlayoutand dropped every other active query arg — keywords, price range, custom-field filters, etc. The top bar now re-emits every other$_GETvalue as a hidden input inside the form (using PHP bracket notation for nested sub-arrays likeregular_price[min]), so the sort round-trip preserves the active filter set. The grid/list switcher anchors already usedadd_query_arg()and were unaffected. - Added: New helper
uclwp_flatten_query_args()that flattens nested arrays intoname[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 atop_bar="enable"attribute (defaultdisable) 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_zoominput (Leafletzoomendand Googlezoom_changedevents 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
columnsshortcode 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’sstyleattribute. The aspect-ratio rule now applies directly to.uclwp-grid-box-wrap .uclwp-imageand.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_subheadingsettings.
- 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 viauclwp_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-listingsso single-listing sidebars and the compare box are unaffected. - Bug fix:
[uclwp_categories](and the underlyingrender_category_image()) no longer renders the saved Bootstrap-icon class. The previous wrapper producedclass="bi bi-{bi bi-house}", an invalid class that resolved to nothing. Output is nowclass="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 applyoverflow: 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.jsnow declaresucl-leaflet-jsas 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.phpfor theuclwp_listingCPT) was rendering without Bootstrap CSS, the icon font, the iconpicker JS, the media uploader, or the map widget. Theload_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’spost_typeisuclwp_listing. Bootstrap stays scoped to.uclwp-bs-wrapperso 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.phpthroughwp_strip_all_tags()after each value is individually escaped viaesc_attr(), with phpcs:ignore annotations explaining why the final concatenation is safe. - Escaping:
paginate_links()output inrender_pagination()now passes throughwp_kses_post()before echoing. - i18n: Added
/* translators: %s ... */comments above twoprintf( 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 inclass-shortcodes.php delete_listing,class-email.php contact_seller,class-favorites.php ajax_toggle, andshortcodes/dashboard/edit.php. The values are still validated throughuclwp_validate_listing_id(). - Sanitization:
$_SERVER['REQUEST_URI']used to build the favorites login-redirect URL now passes throughesc_url_raw( wp_unslash( ... ) )beforehome_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 withwp_send_json( $resp )so character encoding follows WP’s UTF-8 conventions and the response is properly closed viawp_die(). - Plugin Check: Replaced remaining non-AJAX
json_encode()calls (Slick / image-grid data-attributes) withwp_json_encode(). - Plugin Check: Added explicit
timeoutargument (10 s) to everywp_remote_post()call. - Plugin Check: Added
rel="noopener noreferrer"to everytarget="_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);withwp_die();in AJAX handlers. - Plugin Check: Added missing version arguments to every
wp_enqueue_style/wp_enqueue_scriptcall (usedUCLWP_VERSIONfor bundled assets andnullfor third-party CDN scripts whose URL already carries a version key). - Plugin Check: Renamed three filters that were missing the plugin prefix:
no_results_messageuclwp_no_results_message,seller_contact_email_messageuclwp_seller_contact_email_message,raw_uclwp_priceuclwp_raw_price,formatted_uclwp_priceuclwp_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 existingesc_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/$_REQUESTaccess across the plugin now runs throughwp_unslash()before sanitization, matching WordPress core conventions andWPCSrequirements. - Escaping: Replaced
esc_attr_e()/esc_attr__()with the correctesc_html_e()/esc_html__()everywhere the output is HTML body content (labels, table cells, headings, paragraph text). Attribute-context calls (placeholder="",title="",value="",data-*="") remainesc_attr_e(). - Escaping: Replaced
esc_attr()withesc_html()on user-controlled body text — listing titles, seller names, emails, phone numbers, category names, etc. - Escaping: Textarea content now uses
esc_textarea()instead ofesc_attr(). - Bugfix:
compare-box.phpprinted nothing for compare table column headers due toesc_attr( $label )(which returns instead of echoing). Now properlyecho 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_messagesetting in the contact-seller form is now output viawp_kses_post()so admins can include safe HTML formatting (wasesc_attr()which broke the HTML). - Hardening: Search query builder (
uclwp_get_search_query) sanitizes all dynamicorderby,meta_key,tag, andrangeinputs and validates against an allow-list before passing toWP_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 throughsanitize_key(). - Hardening:
class-shortcodes::update_profilecasts and unslashes every$_REQUESTfield. - Hardening: Term-meta image/icon callbacks (
save_category_image,updated_category_image) now checkcurrent_user_can('manage_categories')andwp_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()andselected( $a, $b )used in place of inline($a == $b) ? 'selected' : ''ternaries where the markup allowed it. - Compatibility:
(int) $cat->countand(int) count_user_posts(...)casts inpage-sellers.phpand other admin lists in place ofesc_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_buttonsfilter added so add-ons can inject extra card buttons without forking templates. - Improvement:
uclwp_dashboard_allowed_pagesfilter 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-wrapperso 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 withfilter_var(... FILTER_VALIDATE_IP). - Security: Listing IDs in delete and edit flows are now validated against the
uclwp_listingpost type and authorized viacurrent_user_can('edit_post'|'delete_post', $id)instead of manual ownership checks. - Security: Pending-seller
userindexis cast to integer and validated against existing keys before use. - Security: Permalink-settings save path now requires the core
update-permalinknonce. - Security: Added transient-based rate limiting on login, registration and contact-seller endpoints.
- Security: Asset URLs now include
UCLWP_VERSIONfor 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




