Custom Fields

Custom Fields & Field Types

Listora includes 22 built-in field types organized into 6 categories.

Field Types

Basic

  • Text - Single-line text input
  • Textarea - Multi-line text input
  • Number - Numeric input with optional min/max
  • Email - Email address with validation
  • Phone - Phone number input
  • URL - Website URL with validation

Choice

  • Select - Dropdown select (single value)
  • Multi-Select - Dropdown with multiple selections
  • Checkbox - Single checkbox (yes/no)
  • Radio - Radio button group (single selection)

Date & Time

  • Date - Date picker
  • Time - Time picker
  • Date & Time - Combined date and time

Media

  • Gallery - Image gallery with drag-to-reorder
  • File Upload - File attachment
  • Video - Video URL (YouTube, Vimeo)

Location

  • Map Location - Address with lat/lng coordinates

Structured

  • Business Hours - Weekly hours with open/closed states
  • Social Links - Social media profile URLs
  • Price Range - Price level indicator ($, $$, $$$, $$$$)
  • Color - Color picker
  • Rating - Star rating input

Field Properties

Each field has configurable properties:

Property Description
key Unique field identifier (auto-generated from label)
label Display name shown in forms
type Field type from the list above
required Whether the field is mandatory
searchable Include in full-text search index
filterable Show as a filter option in search
show_in_card Display on listing cards
schema_prop Schema.org property mapping
placeholder Placeholder text for inputs
help_text Helper text below the field
options Available options (for select/radio/checkbox)

Field Groups

Fields are organized into groups for the submission form and detail page:

$field_groups = array(
array(
'key' => 'contact',
'label' => 'Contact Information',
'icon' => 'phone',
'fields' => array(
array( 'key' => 'address', 'type' => 'map_location', 'label' => 'Address' ),
array( 'key' => 'phone', 'type' => 'phone', 'label' => 'Phone' ),
),
),
);

Adding Custom Fields

Use the visual field builder at Listora > Listing Types > Edit Type, or programmatically:

add_filter( 'wb_listora_register_listing_types', function( $types ) {
$types['my-type']['field_groups'][] = array(
'key' => 'custom-group',
'label' => 'Custom Fields',
'fields' => array(
array(
'key' => 'custom_field',
'type' => 'text',
'label' => 'My Custom Field',
'required' => false,
),
),
);
return $types;
});

Social Links field (since 2026-05-12)

The social_links field stores 7 platform URLs as an associative array:

// Stored shape (in _listora_meta JSON or via REST):
array(
'website' => 'https://example.com',
'facebook' => 'https://facebook.com/example',
'twitter' => 'https://twitter.com/example',
'instagram' => 'https://instagram.com/example',
'linkedin' => 'https://linkedin.com/in/example',
'youtube' => 'https://youtube.com/@example',
'tiktok' => 'https://tiktok.com/@example',
)

The canonical 7 platforms are returned by \WBListora\Core\Field::social_link_platforms() so renderers / Pro extensions don't drift. Sanitization is centralized at Field::sanitize_social_links() - every URL passes esc_url_raw + a platform-specific host whitelist (a Facebook URL must be on facebook.com, etc.). The field's schema-generator output emits a sameAs array on the listing's JSON-LD so Google reads the same set.

To add an 8th platform, filter wb_listora_social_link_platforms:

add_filter( 'wb_listora_social_link_platforms', function ( array $platforms ): array {
$platforms['threads'] = array(
'label' => 'Threads',
'icon' => 'message-circle',
'host' => 'threads.net',
);
return $platforms;
} );

Registering a custom field type

The 22 built-in types live in \WBListora\Core\Field_Registry. To add your own type:

add_filter( 'wb_listora_field_types', function ( array $types ): array {
$types['my_special_field'] = array(
'label' => __( 'My Special Field', 'my-plugin' ),
'category' => 'choice', // 'basic' | 'choice' | 'date_time' | 'media' | 'location' | 'structured'
'sanitizer' => array( My_Field_Handler::class, 'sanitize' ),
'renderer' => array( My_Field_Handler::class, 'render_submission' ),
'display' => array( My_Field_Handler::class, 'render_display' ),
'searchable' => true,
'filterable' => false,
);
return $types;
} );

The handler is responsible for:

  • Sanitization at REST + admin entry points (sanitize($value, $field_config): mixed).
  • Submission rendering - the form field HTML inside the submission wizard.
  • Display rendering - the read-side HTML on the detail page.

Once registered, the new type appears in the Listing Types admin field-builder dropdown and accepts REST + WP-CLI imports like any built-in type.

Related