A full-featured classified ads marketplace for your Larapen site. Users can create, browse, search, and manage listings with custom fields, location filtering, image galleries, and built-in messaging: all with admin moderation and granular permissions.

Custom Fields

Define unlimited custom fields per category or globally. Support for 10 field types including text, select, checkbox, date, and price range.

Moderation System

Optional admin approval workflow. Approve, reject (with reason), or auto-publish listings. Configurable per-site.

Search & Filtering

Full-text search across titles, descriptions, and locations. Filter by category, price range, condition, city, and custom fields.

Buyer-Seller Messaging

Built-in contact form with email notifications. Messages tracked per listing with read/unread status.

Favorites & Saved

Authenticated users can bookmark listings for later. Toggle save/unsave with a single click.

Multi-Language

All listing content, categories, and custom fields are translatable via spatie/laravel-translatable. Full i18n support.

Auto-Expiration

Listings expire after a configurable number of days. Expired listings are automatically hidden from public view.

Community Reporting

Users can report inappropriate listings. Admins review, dismiss, or act on reports from a dedicated panel.

Use Cases

General Marketplace

Run a Craigslist-style classified ads board where users post items for sale, services, or rentals. Categories and custom fields let you structure any type of listing.

  • Enable user registration and listing creation.
  • Define categories (Vehicles, Electronics, Real Estate, Jobs, etc.) with category-specific custom fields.
  • Enable moderation to review submissions before they go live.
  • Buyers message sellers directly through the built-in contact form.

Business Directory

Create a directory of local businesses with custom fields for opening hours, services offered, and contact details.

  • Disable the price field or make it optional.
  • Add custom fields like “Opening Hours”, “Website URL”, and “Services Offered”.
  • Use location fields (city, region, address) for geographic filtering.

Internal Asset Board

A private board for an organization to list and exchange internal assets, equipment, or resources.

  • Disable guest browsing: require login to view listings.
  • Disable public publishing: only admins create listings.
  • Use the “condition” field (new, used, refurbished) for asset tracking.

Requirements

Requirement Details
Larapen Core ≥ 1.0.0
PHP ≥ 8.2
MySQL ≥ 8.0
User Accounts Required: the add-on depends on the core users table for listing ownership, messaging, favorites, and reporting.
Dependencies None: no other add-ons required.

Installation

Step 1: Upload the Add-on

In the admin panel, go to Admin → Extensions → Add-ons and click the Upload Add-on button. Select the add-on’s ZIP file: the system extracts it automatically and the add-on appears in the installed add-ons list.

Step 2: Activate the Add-on

Find Classified Ads in the list and click Activate. Its migrations, seeders (if any) and permissions are set up automatically.

Step 3: Configure

Navigate to Admin → Classified Ads → Settings to configure categories, pricing plans, moderation rules, and notifications. See Configuration.

Purchase Code (License Key)

Classified Ads is sold as a separate product, so it has its own purchase code (license key), distinct from the purchase code of the main application and from the one of every other add-on. You are asked for it when you activate Classified Ads in Admin panel → Add-ons.

Our products are sold on three platforms. The way you receive a purchase code depends on where you bought the product.

Platform / Marketplace How you get the purchase code Where to find it again
bedigit.com Store
In-site purchase (Shop)
Generated automatically when the order is paid, then sent by email, either in its own license email, or inside the order confirmation email. My Account → My Licenses on bedigit.com
Gumroad Created as soon as Gumroad notifies us of the sale, then sent in a separate email, in addition to the Gumroad receipt. The license email, your Gumroad Library, and My Account → My Licenses on bedigit.com
Envato Market
CodeCanyon
Issued by Envato, not by us, and never sent by email: you download it yourself from your Envato account. Envato account → Downloads → License certificate & purchase code
Check your spam folder. For both bedigit.com Store and Gumroad purchases, the purchase code is delivered by email. Automated license emails are very often filtered, so if the message is not in your inbox, look in your spam / junk folder before contacting support, and add our sender address to your contacts or allow list.

1. bedigit.com Store (in-site purchase)

  • As soon as the order’s payment status becomes Paid, a license key is generated automatically for every licensed item in the order (one key per purchased unit: buying 3 units gives 3 distinct keys).
  • It is emailed to the address used on the order, either in a dedicated license email or inside the order confirmation email. Check your inbox and your spam / junk folder.
  • The key stays available in your account under My Account → My Licenses. Keys are masked in the list; open the license detail page to reveal and copy the full key, see the domains it is activated on, and deactivate a domain to free an activation slot.
  • The matching invoice is under My Account → My Orders.

2. Gumroad

  • A Gumroad purchase produces two separate emails: the Gumroad receipt (sent by Gumroad, giving access to the files) and a license key email (sent by bedigit.com) that contains your purchase code.
  • The license key email is generated as soon as Gumroad notifies us of the sale, so it normally arrives within seconds of the payment. Here too, check your inbox and your spam / junk folder.
  • When the Gumroad product uses Gumroad’s own license-key feature, the same key also appears in your Gumroad receipt and under Library → your purchase on gumroad.com.
  • Use the same email address on bedigit.com as on Gumroad: your keys are then linked to your account automatically and listed under My Account → My Licenses, even if you register after the purchase. You can also add a Gumroad key manually from My Account → My Gumroad Licenses.

3. Envato Market (CodeCanyon)

  • Envato purchase codes are issued and delivered by Envato Market, never emailed by us, so there is nothing to look for in your spam folder: you retrieve the code from your Envato account.
  • Log in to your Envato / CodeCanyon account, open the Downloads page, find the item, and choose License certificate & purchase code from the Download dropdown. The code is written in that certificate.
  • An Envato purchase code looks like 12345678-90ab-cdef-1234-567890abcdef (8-4-4-4-12 characters). It never changes, and renewing item support does not issue a new one.
  • Official Envato article: Where Is My Purchase Code?
Lost your purchase code? Search your mailbox (spam folder included) for “license” or “purchase code”, then check My Account → My Licenses on bedigit.com for Store and Gumroad purchases, or Downloads → License certificate on Envato. If it is still missing, open a ticket on our Help Center with your order number (Store), Gumroad sale ID or buyer email (Gumroad), or Envato username and item name (Envato).

Configuration

Configuration defaults are defined in config/classified.php and can be overridden via admin settings (stored in the database with the classified_ prefix).

Setting Key Type Default Description
per_page int 12 Listings per page on the front-end
admin_per_page int 15 Listings per page in the admin panel
max_images int 5 Maximum images per listing (featured + gallery)
listing_duration_days int 30 Days until a listing expires (0 = never expires)
allow_publishing bool true Allow users to create listings on the front-end
guest_browse bool true Allow non-authenticated visitors to browse listings
guest_contact bool false Allow guests to send messages to sellers
moderation_enabled bool true Require admin approval before listings go live
require_phone bool false Make phone number mandatory on listings
enable_reports bool true Allow users to report listings
enable_favorites bool true Allow users to save/bookmark listings
allow_author_translations bool true Allow listing authors to provide translations

Notification Settings

Each notification can be individually enabled or disabled from the admin settings panel:

Setting Key Default Description
notify_admin_on_new_listing true Notify admins when a new listing is submitted
notify_author_on_new_listing true Send confirmation email to listing author
notify_author_on_approval true Notify author when their listing is approved
notify_author_on_rejection true Notify author when their listing is rejected
notify_owner_on_new_message true Notify listing owner when a new message is received
notify_admin_on_report true Notify admins when a listing is reported
notify_owner_on_expiration true Notify listing owner when their listing expires

Admin: Settings

Access via Admin → Classified Ads → Settings. The settings page is organized into logical sections:

  • Publishing: Toggle user listing creation, guest browsing, and guest contact.
  • Moderation: Enable/disable admin approval for new listings.
  • Listing Duration: Set how many days listings remain active (0 for unlimited).
  • Images: Maximum number of images per listing.
  • Contact Info: Whether phone number is required.
  • Features: Enable/disable reporting and favorites.
  • Translations: Allow authors to provide multi-language content.
  • Notifications: Toggle each of the 7 notification types.
GET /admin/classified/settings

Displays the settings form with current values.

PUT /admin/classified/settings

Saves all settings. Validated via UpdateClassifiedSettingsRequest.

Admin: Listings

The listings management page provides a paginated table of all listings with filtering by status and category. Each row shows the listing title, author, category, status badge, price, view count, message count, report count, and creation date.

GET /admin/classified/listings
Query Parameters
statusFilter by status (draft, pending_review, published, expired, rejected, sold)
category_idFilter by category ID

Create & Edit

The listing form includes fields for:

  • Content: Title (translatable), content/description (translatable), meta title, meta description
  • Classification: Category selection, item condition (new, used, refurbished)
  • Pricing: Price, currency, negotiable flag
  • Location: City, region, country, address, latitude/longitude
  • Contact: Contact name, email, phone
  • Media: Featured image + gallery images (up to max configured)
  • Custom Fields: Dynamic fields loaded based on the selected category (via AJAX)
  • Status: Draft, pending review, published (admin can bypass moderation)
  • Options: Featured toggle, expiration date, position
GET /admin/classified/listings/create

Listing creation form.

POST /admin/classified/listings

Store a new listing. Validated via Admin\StoreListingRequest. Handles image uploads and custom field values.

GET /admin/classified/listings/{listing}/edit

Edit form for an existing listing.

PUT /admin/classified/listings/{listing}

Update an existing listing. Supports replacing the featured image, adding/removing gallery images, and updating custom field values.

DELETE /admin/classified/listings/{listing}

Delete a listing and all associated media, custom field values, messages, reports, and saved entries (via cascade).

Moderation

When moderation is enabled, new listings are set to pending_review status. Admins can approve or reject them:

POST /admin/classified/listings/{listing}/approve

Sets the listing status to published, records the publication date, and clears any rejection reason. Sends an approval notification to the author (if enabled).

POST /admin/classified/listings/{listing}/reject
Request Body
reasonRequired: the rejection reason (sent to the author via email)

Admin: Categories

Classified categories use the core unified categories table with categorizable_type = 'listing'. Categories support nesting (parent/child hierarchy via nested set) and are translatable.

GET /admin/classified/categories

Paginated nested tree view of all listing categories.

POST /admin/classified/categories

Create a new category. Validated via StoreCategoryRequest. Fields: name (translatable), slug (translatable), description (translatable), meta title, meta description, parent category, position, active status.

PUT /admin/classified/categories/{category}

Update a category and rebuild the nested set tree.

DELETE /admin/classified/categories/{category}

Delete a category. Listings in the deleted category will have their category_id set to null.

Admin: Custom Fields

Custom fields allow you to extend listings with category-specific or global attributes. Fields can be marked as filterable (shown in search filters) and searchable (included in full-text search).

GET /admin/classified/custom-fields

Paginated list of all custom fields with category filter.

POST /admin/classified/custom-fields
Fields
nameTranslatable: field label
slugUnique identifier
typeOne of the 10 supported field types
category_idNullable: null means the field applies to all categories
placeholderTranslatable: placeholder text
help_textTranslatable: help text shown below the field
optionsJSON array: for select, checkbox, and radio types
is_requiredWhether the field is mandatory
is_filterableShow in search/filter sidebar
is_searchableInclude in full-text search
min_value / max_valueValidation bounds for numeric fields
positionDisplay order

Supported Field Types

Type Value Has Options? HTML Input
TexttextNo<input type="text">
TextareatextareaNo<textarea>
NumbernumberNo<input type="number">
SelectselectYes<select>
CheckboxcheckboxYes<input type="checkbox">
RadioradioYes<input type="radio">
DatedateNo<input type="date">
Price Rangeprice_rangeNo<input type="number">
URLurlNo<input type="url">
EmailemailNo<input type="email">
Dynamic Loading: Custom fields are loaded dynamically via AJAX when the user selects a category on the listing form. The endpoint GET /api/classified/custom-fields/{categoryId?} returns the relevant fields for that category (plus any global fields).

Admin: Messages

View all messages sent through listing contact forms. Messages can be filtered by read/unread status.

GET /admin/classified/messages

Paginated list of messages with sender, listing, date, and read status. Supports filtering by unread messages.

GET /admin/classified/messages/{message}

View message details. Automatically marks the message as read.

DELETE /admin/classified/messages/{message}

Delete a message permanently.

Admin: Reports

View and manage listing reports submitted by users. Reports include a reason (spam, inappropriate, fraud, wrong category, duplicate, or other) and an optional description.

GET /admin/classified/reports

Paginated list of reports with status filter (pending, reviewed, dismissed).

PUT /admin/classified/reports/{report}

Review a report: set status to reviewed or dismissed. Records the reviewer and review timestamp.

DELETE /admin/classified/reports/{report}

Delete a report permanently.

Report Reasons

Value Description
spamListing is spam or unsolicited advertising
inappropriateContent violates community guidelines
fraudSuspected fraudulent listing
wrong_categoryListing is in the wrong category
duplicateDuplicate of another listing
otherOther reason (user provides description)

Front-End: Browsing & Search

The public classifieds page shows published, non-expired listings ordered by featured status, publication date, and position. Visitors can filter and search listings using multiple criteria.

Search & Filter Options

Filter Parameter Description
Keyword SearchsearchFull-text search in title, content, city, and region
Categorycategory_idFilter by category
CitycityLocation-based filtering (LIKE match)
Price Minprice_minMinimum price threshold
Price Maxprice_maxMaximum price threshold
ConditionconditionItem condition (new, used, refurbished)
Guest Access: Browsing can be restricted to authenticated users only by setting guest_browse to false in the admin settings. When disabled, the ClassifiedGuestAccess middleware redirects unauthenticated visitors to the login page.

Category Browsing

Access via /classifieds/category/{slug}. Shows listings filtered by the specified category, with full search and filtering available within that category.

Front-End: Listing Detail

Access via /classifieds/{slug}. The listing detail page includes:

  • Full title, description, and custom field values
  • Image gallery (featured image + additional gallery images)
  • Price with currency formatting and negotiable indicator
  • Item condition badge
  • Location information (city, region, country, address)
  • Seller contact information
  • Contact form (for sending a message to the seller)
  • Save/unsave button (for authenticated users)
  • Report button (for authenticated users)
  • Related listings (same category or same city)
  • View count (incremented on each visit)

Front-End: Create & Edit Listings

Authenticated users can create and edit their own listings from the front-end. This feature can be disabled site-wide by setting allow_publishing to false.

GET /classifieds/create/new

Listing creation form. Requires authentication. Protected by CheckPublishingEnabled middleware.

POST /classifieds/create/new

Submit a new listing. Validated via Front\StoreListingRequest. When moderation is enabled, the listing is set to pending_review and requires admin approval.

GET /classifieds/{listing}/edit

Edit form for a listing. Only the listing owner can access this page.

PUT /classifieds/{listing}/edit

Update a listing. Validated via Front\UpdateListingRequest.

Moderation: When moderation is enabled, newly created listings are automatically set to pending_review status (even if the user selects “published”). Only admin-created listings or admin-approved listings bypass moderation.

Front-End: My Listings

Access via /classifieds/my/listings. Authenticated users can view all their listings with status-based tabs: all, active, pending, expired, sold, and draft.

From this page, users can:

  • View listing status and message count
  • Edit their listings
  • Delete their listings
DELETE /classifieds/{listing}

Delete a listing. Only the listing owner can perform this action.

Front-End: Saved Listings

Access via /classifieds/my/saved. Users can bookmark listings and view them later from a dedicated saved listings page.

POST /classifieds/{listing}/save

Toggle save/unsave for a listing. Returns whether the listing is now saved (true) or unsaved (false). Works as an AJAX toggle.

Feature Toggle: The favorites feature can be disabled entirely by setting enable_favorites to false in admin settings.

Front-End: Contact Seller

Each listing detail page includes a contact form that sends a message to the listing owner.

POST /classifieds/{listing}/contact
Request Body
sender_nameRequired: sender’s name
sender_emailRequired: sender’s email
sender_phoneOptional: sender’s phone
messageRequired: the message body

Guest contact can be controlled via the guest_contact setting. When disabled, only authenticated users can send messages.

Front-End: Reporting

Authenticated users can report listings that violate community guidelines.

POST /classifieds/{listing}/report
Request Body
reasonRequired: one of: spam, inappropriate, fraud, wrong_category, duplicate, other
descriptionOptional: additional details about the report

Notifications

The add-on includes 7 email notification classes, all extending BaseNotification and using the mail channel. Each notification can be individually toggled via admin settings.

Notification Recipient Trigger Setting
NewListingAdminNotification Admin users New listing submitted notify_admin_on_new_listing
ListingConfirmationNotification Listing author Listing submitted notify_author_on_new_listing
ListingApprovedNotification Listing author Listing approved by admin notify_author_on_approval
ListingRejectedNotification Listing author Listing rejected by admin notify_author_on_rejection
NewMessageNotification Listing owner New contact message received notify_owner_on_new_message
ListingReportedNotification Admin users Listing reported by a user notify_admin_on_report
ListingExpiredNotification Listing owner Listing expires notify_owner_on_expiration
Fallback: If a listing has no associated user (e.g., deleted user), notifications are sent to the contact_email address on the listing using on-demand notification routing.

Updating

There are two ways to update this add-on: via the admin panel (recommended) or manually replacing files.

Method 1: Admin Panel Upload (Recommended)

  1. Download the latest .zip file of this add-on.
  2. Go to Admin panel → Add-ons and click the Upload button.
  3. Select or drag the .zip file into the upload area.
  4. A confirmation prompt will show the current and new version numbers. Click Replace to proceed.
  5. Go to Admin panel → System Update (/admin/update) to apply any pending database migrations.

Method 2: Manual File Replacement

Step 1: Replace Files

Replace the add-on directory with the new version.

Step 2: Run Migrations

php artisan migrate

Pending migrations run once, so the command is safe to repeat.

Step 3: Clear Caches

php artisan config:clear
php artisan route:clear
php artisan view:clear

Step 4: Verify

Visit Admin → Classified Ads → Settings and confirm all settings are intact. Browse the classifieds page to verify listings display correctly.

Backup first: Always back up your database before running migrations on a production system.

Uninstallation

Switching an add-on off without losing anything is a deactivation: go to Admin panel → Add-ons, find Classified Ads and click Deactivate.

  • Its routes, views, admin menu entries and permissions stop being registered, and its front-end pages stop answering.
  • Its database tables and all the data they hold are kept, and its files stay under extensions/addons/classified/. Nothing is deleted.
  • The purchase code recorded at activation is kept too, so activating the add-on again does not ask for it.
  • Deactivation is refused while another active add-on depends on this one: deactivate that add-on first.

Click Activate on the same card to switch it back on. Pending migrations are re-run, assets are republished, and the add-on picks up exactly where it left off.

Removing

Removing is permanent and destroys the add-on's data. The Remove button only appears on a deactivated add-on, so removal is always two steps:

  1. Deactivate Classified Ads (see Uninstallation).
  2. Click Remove on its card and confirm the prompt.

The admin panel then, in one pass:

  • runs the add-on's uninstall hook, if it ships one, while its code is still on disk;
  • revokes the permissions declared in its addon.json;
  • rolls back its migrations (this drops its database tables and every row they hold) and purges its entries from the migrations table, so a later reinstall migrates from scratch;
  • deletes its published assets: public/addons/classified/, public/vendor/classified/ and storage/app/public/addons/classified/;
  • deletes the add-on directory extensions/addons/classified/;
  • deletes its row in the addons table (the recorded purchase code goes with it) and clears the application cache.
This cannot be undone. Back up your database before removing an add-on whose data you may still need: installing it again later creates empty tables, not your old content.

Removal is refused, with an explanatory message and before anything is destroyed, when the add-on is still active, when another active add-on depends on it, or when the web server (PHP) user cannot delete extensions/addons/classified/. In that last case, give that user write permission on the directory and on its parent, then try again.

Deleting the folder over FTP or SSH is not equivalent: the add-on's tables, its entries in the migrations table and its addons row are all left behind, and its card stays in the list. Use Remove in the admin panel instead.

Troubleshooting

Listings not visible on the front-end

Check that:

  • The listing status is published (not draft, pending, expired, rejected, or sold).
  • The published_at date is in the past.
  • The expires_at date is either null or in the future.
  • Guest browsing is enabled if you are not logged in (check guest_browse setting).

Users cannot create listings

  • Ensure allow_publishing is set to true in admin settings.
  • Verify the user is authenticated (listing creation requires login).
  • Check the CheckPublishingEnabled middleware is not blocking access.

Custom fields not appearing on the listing form

  • Ensure the custom field is active (is_active = true).
  • Verify the field is either global (category_id = null) or assigned to the selected category.
  • Check the browser console for AJAX errors on the /api/classified/custom-fields/ endpoint.
  • Ensure JavaScript is enabled and the category select element triggers the AJAX call.

Listings stuck in “Pending Review”

  • Moderation is enabled by default. Go to Admin → Classified Ads → Listings and approve pending listings.
  • To disable moderation, set moderation_enabled to false in admin settings. New listings will be published immediately.

Notifications not being sent

  • Verify the corresponding notification setting is enabled (e.g., notify_admin_on_new_listing).
  • Ensure your mail configuration is correct in .env (SMTP, Mailgun, etc.).
  • Check the Laravel log (storage/logs/laravel.log) for mail errors.
  • If the listing has no associated user, ensure the contact_email is set on the listing for fallback delivery.

Expired listings still showing

  • The expireOldListings() method in ClassifiedService must be called to update status. This should be scheduled as a cron job or artisan command.
  • Listings with expires_at in the past are automatically excluded from the active() scope, but their status field is only updated when the expiration process runs.

Images not uploading

  • Check PHP’s upload_max_filesize and post_max_size settings.
  • Verify the storage directory is writable.
  • Ensure you have not exceeded the max_images limit configured in admin settings.

Category listing counts incorrect

  • Listing counts are computed dynamically via withCount. If counts seem stale, clear the application cache: php artisan cache:clear.

Save/favorite toggle not working

  • Ensure the user is authenticated (saving requires login).
  • Verify enable_favorites is set to true in admin settings.
  • Check the browser console for AJAX errors on the toggle endpoint.
  • Ensure the CSRF token is included in the request headers.

Classified Ads v1.0.0: Part of the Larapen CMS platform.

© BeDigit. All rights reserved.

Was this article helpful?

Thank you for your feedback!

Still need help? Create a support ticket

Create a Ticket
Apr 07, 2026