> For the complete documentation index, see [llms.txt](https://ovatheme.gitbook.io/brw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ovatheme.gitbook.io/brw/brw-menu/custom-checkout-fields.md).

# Custom Checkout Fields

## Watch The Video Tutorial

{% embed url="<https://youtu.be/bcfEe4fGQaQ>" %}

### 1: Introduction

Custom Checkout Fields (CCF) are **global field definitions** that appear on the booking form when customers are selecting a rental. Unlike Specifications (which display static info about a product), CCF fields collect **input from customers at checkout** — and can optionally charge an extra price per selection.

{% hint style="info" %}
Examples: "Special requests" (textarea), "Pick-up sign name" (text), "Driver age" (number), "Add baby seat?" (checkbox with price), "Insurance tier" (radio with pricing per option), "Passport copy" (file upload).
{% endhint %}

### 2: How It Works

| Step                        | Where                                                     | What happens                                                                                 |
| --------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| **1. Define fields**        | BRW → Custom Checkout Fields                              | Create global field definitions (type, label, options, pricing, validation)                  |
| **2. Assign to category**   | Products → Categories → Edit                              | Choose which fields appear on products in each category (All, None, or pick specific fields) |
| **3. Override per product** | Product Edit → Advanced Settings → Custom checkout fields | Override the category setting: show all (category), pick local fields, or hide all           |
| **4. Customer fills in**    | Single product page booking form                          | Enabled, assigned fields render in the booking form before the customer submits              |
| **5. Saved to booking**     | Booking detail / order meta                               | Customer-entered values are stored in the booking and visible in the admin booking detail    |

### 3: Fields List — Table Columns

<figure><img src="/files/qP1pnd0D3YtOlLyb1uBj" alt=""><figcaption></figcaption></figure>

| Column       | Description                                                                                                                       |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| **Checkbox** | Select for bulk actions. "Select all" in header/footer selects all rows.                                                          |
| **Type**     | Field type label. A hidden input in the same cell stores the type value for form operations.                                      |
| **Name**     | Internal slug/key (unique, lowercase, no spaces). Used as the array key in `ovabrw_booking_form`.                                 |
| **Label**    | Human-readable display name shown to customers on the booking form.                                                               |
| **Required** | Green checkmark (✓) = field is required. Blank = optional. Customers cannot submit without filling required fields.               |
| **Enabled**  | Green checkmark (✓) = active, appears on booking form. Blank = disabled (hidden from customers). Disabled rows appear greyed out. |
| **Actions**  | Edit (✏), Visibility toggle (👁 disable / 🚫 enable), Delete (🗑), Drag handle (⣿) for reordering.                                |

#### Bulk Actions

Six buttons at the top of the page. **Add field** requires no selection; the rest operate on checked rows.

| Button        | Action                    | Behavior                                                                                       |
| ------------- | ------------------------- | ---------------------------------------------------------------------------------------------- |
| **Add field** | Open Add popup            | Opens the Add New Field popup. Always visible; no rows need to be checked.                     |
| **Required**  | Mark selected as required | Sets `required = 'on'` for all checked fields. Customers must fill these in before submitting. |
| **Optional**  | Mark selected as optional | Sets `required = ''` for all checked fields.                                                   |
| **Enable**    | Enable selected           | Sets `enabled = 'on'` for all checked fields. Active fields appear in the booking form.        |
| **Disable**   | Disable selected          | Sets `enabled = ''` for all checked fields. Hidden from booking forms; row appears greyed out. |

{% hint style="warning" %}
**Bulk actions except Add field require selections.** Clicking Required / Optional / Enable / Disable / Delete with no checkboxes checked does nothing.
{% endhint %}

#### Row Actions

**Edit**

* Opens the Edit popup pre-filled with the field's current configuration

**Visibility Toggle**

* Toggles a single field between enabled (👁 = active, click to disable) and disabled (🚫 = active, click to enable). Saves via AJAX without page reload. Disabled rows are visually dimmed.

**Delete**

* Deletes this single field immediately. No confirmation prompt. Existing booking data referencing this field name is not removed from the database.

**Drag & Drop Reorder**

* Drag rows to change display order. Order is saved automatically via AJAX on drop. The booking form renders fields in this order.

### 4: Add / Edit Popup — All Fields

<figure><img src="/files/0WN7tsDsOE6RtQeg9fO8" alt=""><figcaption></figcaption></figure>

**Select Type** <mark style="color:$danger;">- Required</mark>

* Dropdown with 12 types. Changing the type dynamically shows/hides type-specific fields (Options table, Min/Max, file format notice, etc.).

  For File type, a notice shows accepted formats: *.jpg, .jpeg, .png, .pdf, .doc*. A **Max size** field also appears (default: 20MB).

**Max size**\
\- Maximum file size in MB that customers can upload. Default: `20` (20MB). Stored as `max_file_size`.

**Options**

* A sortable table of selectable options. Each option can have an optional **Price** added to the booking total when chosen, plus **Min quantity** and **Max quantity** limits per booking. See Options & Pricing for full details.

**Name -** <mark style="color:$danger;">Required</mark>

* Internal identifier. Rules: **unique**, **lowercase only**, **no spaces** . Renaming in Edit rearranges the key in the global array while preserving order.

**Label -** <mark style="color:$danger;">Required</mark>

* Display name shown to customers on the booking form (e.g. "Special Request", "Add baby seat?").

**Description -** <mark style="color:$success;">Option</mark>

* Textarea for a longer helper text shown beneath the field on the booking form. Useful for explaining requirements or acceptable formats.

**Placeholder**

* Placeholder text inside the input field (e.g. "Enter your full name as it appears on your ID"). Hidden for types that don't use a text input.

**Default**

* Pre-filled default value. The input control varies by type:
*

```
| Type                   | Default input control              |
```

```
| ---------------------- | ---------------------------------- |
| Text Textarea Password | Text input                         |
| Number                 | Number input                       |
| Tel                    | Tel input (`type="tel"`)           |
| Email                  | Email input (`type="email"`)       |
| Date                   | Date picker (BRW datepicker)       |
| Price                  | Text input for default price value |
| Radio Checkbox Select  | Text input (free-text default)     |
| File                   | — (no Default field shown)         |
```

**Min / Max**

* Numeric constraints for the Number type input

**Min / Max date**

* Date picker constraints for the Date type

**Min price / Max price / Step**

* For the Price type (slider), these three values are required:

  **Min price** — the lowest value on the slider. **Max price** — the highest value. **Step** — how much each slider tick increments (default: `10`).

  The selected price is added to the booking total.

**Class -** <mark style="color:$success;">Option</mark>

* Extra CSS class on the field wrapper on the frontend. Use for custom styling or targeting with JS.

**Required / Enabled (checkboxes)**

* **Required** (unchecked by default): if checked, the booking form will not submit until the customer provides a value.
* **Enabled** (checked by default): if unchecked, the field is hidden from all booking forms regardless of category/product assignment

**Field Types**

12 input types are available.

| Type     | Frontend input                          | Use case                                         | Supports pricing |
| -------- | --------------------------------------- | ------------------------------------------------ | ---------------- |
| Text     | Single-line text (`type="text"`)        | Name on sign, pickup sign text, reference number | —                |
| Number   | Number input with optional Min/Max      | Number of extra luggage, driver age              | —                |
| Tel      | Phone input (`type="tel"`)              | Customer contact number for pickup               | —                |
| Email    | Email input (`type="email"`)            | Alternate contact email                          | —                |
| Password | Password input (masked)                 | Access code, PIN for a locker                    | —                |
| Textarea | Multi-line textarea                     | Special requests, delivery notes, instructions   | —                |
| Radio    | Radio button group — one selection only | Insurance tier, fuel option (one choice)         | ✓ Per option     |
| Checkbox | Checkbox group — multiple selections    | Add-ons: baby seat, GPS, child booster           | ✓ Per option     |
| Select   | Dropdown select                         | Preferred vehicle color, city drop-off           | ✓ Per option     |
| Date     | Date picker (BRW datepicker widget)     | Preferred delivery date, return date override    | —                |
| File     | File upload (.jpg/.jpeg/.png/.pdf/.doc) | Passport copy, driver's license, signed form     | —                |
| Price    | Range slider (Min/Max/Step required)    | Tip amount, voluntary insurance contribution     | ✓ Slider value   |

**Options & Pricing**

* Radio, Checkbox, and Select types have a sortable options table in the popup. Each option row can carry an extra price that is added to the booking total when selected.

<figure><img src="/files/WNdfQ2qv1MpYsHpN2Ukn" alt=""><figcaption></figcaption></figure>

| Column                                       | Type(s)          | Description                                                                                                                                                                   |
| -------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Value** (Radio) / **ID** (Checkbox/Select) | All              | Internal key: unique, lowercase, no spaces. For Radio, this is also the display text. Stored in `ova_values[]` (radio) or `ova_checkbox_key[]` / `ova_options_key[]`.         |
| **Value** (Checkbox/Select only)             | Checkbox, Select | Human-readable text shown to customers for this option. Stored in `ova_checkbox_text[]` / `ova_options_text[]`.                                                               |
| **Price**                                    | All              | Extra price added to the booking total when this option is selected. Leave blank for no surcharge. Stored in `ova_prices[]` / `ova_checkbox_price[]` / `ova_options_price[]`. |
| **Min quantity**                             | All              | Minimum number of times this option can be selected per booking. Leave blank for no minimum. Stored in `ova_min_qtys[]` etc.                                                  |
| **Max quantity**                             | All              | Maximum number of times this option can be selected per booking. Leave blank for unlimited. Stored in `ova_qtys[]` etc.                                                       |
| **Actions**                                  | All              | **+** adds a new row below, **×** removes the row, drag handle (⠿) reorders options.                                                                                          |

### 5: Category-level Assignment

Each rental category can specify which custom checkout fields appear on products in that category. Configure this in **Products → Categories → Edit category → Custom checkout fields**.

| Option                | Behavior                                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **All**               | All enabled custom checkout fields appear on products in this category.                                            |
| **New** (pick fields) | Only the fields selected in the *Custom checkout fields* multi-select appear. Stored in `custom_checkout_field[]`. |
| **None**              | No custom checkout fields appear on products in this category.                                                     |

{% hint style="info" %}
The multi-select for "New" shows only enabled fields (disabled fields are filtered out). Fields are listed in the order set by drag-and-drop sorting on the Custom Checkout Fields page; previously selected fields are shown first.
{% endhint %}

### 6: Product-level Override

Each product can override its category's assignment via **Product Edit → Advanced Settings → Custom checkout fields**.

| Option               | Behavior                                                                                                                        |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Category setting** | Uses the category's configuration. Default value for all products.                                                              |
| **Local**            | Overrides the category — shows only the fields selected in the multi-select below. Stored in `product_custom_checkout_field[]`. |
| **None**             | Hides all custom checkout fields on this product's booking form, regardless of category setting.                                |

{% hint style="info" %}
The "Select checkout fields" multi-select only shows **enabled** fields. Disabled fields are excluded.
{% endhint %}

### 7: In Booking Detail

Customer-entered values for custom checkout fields are saved with the booking and displayed in the admin booking detail view.

| Field type                     | How it appears                                                           |
| ------------------------------ | ------------------------------------------------------------------------ |
| Text Number Tel Email Textarea | Renders the entered value as-is with the field label.                    |
| Radio                          | Shows the selected option value (and price, if any was charged).         |
| Checkbox                       | Shows each checked option (ID → display value) and any associated price. |
| Select                         | Shows the selected option's display text and any associated price.       |
| Date                           | Shows the selected date.                                                 |
| File                           | Link or preview of the uploaded file attachment.                         |
| Price                          | Shows the selected slider price value.                                   |

### 8: Manage Custom Checkout Fields in Backend

You can see custom checkout field of an specific order in backend

<figure><img src="/files/jDdTE0QMjRd7eE04pc6W" alt=""><figcaption></figcaption></figure>

### 9: PHP Filters & Actions

| Hook                                                         | Type   | Description                                                                                           |
| ------------------------------------------------------------ | ------ | ----------------------------------------------------------------------------------------------------- |
| `ovabrw_submenu_cckf_capability`                             | Filter | WordPress capability required to access the Custom Checkout Fields admin page. Default: `edit_posts`. |
| `ovabrw_cckf_get_types`                                      | Filter | Add or remove field types from the Type dropdown. Receives and must return the types array.           |
| `ovabrw_cckf_min_year`                                       | Filter | Minimum year for the Date type picker year dropdown. Default: `gmdate('Y') - 125`.                    |
| `ovabrw_cckf_max_year`                                       | Filter | Maximum year for the Date type picker year dropdown. Default: `gmdate('Y') + 3`.                      |
| `ovabrw_cckf_min_date`                                       | Filter | Minimum selectable date for the Date type picker. Default: `''` (no limit).                           |
| `ovabrw_cckf_max_date`                                       | Filter | Maximum selectable date for the Date type picker. Default: `''` (no limit).                           |
| `ovabrw_before_cckf_html`                                    | Action | Fires before the main Custom Checkout Fields page HTML. Receives `$this` (CCKF class instance).       |
| `ovabrw_after_cckf_html`                                     | Action | Fires after the main Custom Checkout Fields page HTML.                                                |
| `ovabrw_before_popup_cckf_html`                              | Action | Fires before the popup HTML (Add or Edit).                                                            |
| `ovabrw_after_popup_cckf_html`                               | Action | Fires after the popup HTML.                                                                           |
| `ovabrw_before_popup_add_cckf`                               | Action | Fires inside the Add popup before standard fields. Receives `$action, $type, $name`.                  |
| `ovabrw_after_popup_add_cckf`                                | Action | Fires inside the Add popup after standard fields (before status checkboxes).                          |
| `ovabrw_before_add_cckf`                                     | Action | Fires before a new field is saved. Receives `$post, $this`.                                           |
| `ovabrw_after_add_cckf`                                      | Action | Fires after a new field is saved.                                                                     |
| `ovabrw_before_edit_cckf`                                    | Action | Fires before a field is updated. Receives `$post, $this`.                                             |
| `ovabrw_after_edit_cckf`                                     | Action | Fires after a field is updated.                                                                       |
| `ovabrw_before_delete_cckf`                                  | Action | Fires before field(s) are deleted.                                                                    |
| `ovabrw_after_delete_cckf`                                   | Action | Fires after field(s) are deleted.                                                                     |
| `ovabrw_before_required_cckf` / `ovabrw_after_required_cckf` | Action | Fire before/after bulk Required action.                                                               |
| `ovabrw_before_optional_cckf` / `ovabrw_after_optional_cckf` | Action | Fire before/after bulk Optional action.                                                               |
| `ovabrw_before_enable_cckf` / `ovabrw_after_enable_cckf`     | Action | Fire before/after bulk Enable action.                                                                 |
| `ovabrw_before_disable_cckf` / `ovabrw_after_disable_cckf`   | Action | Fire before/after bulk Disable action.                                                                |
| `ovabrw_before_sort_cckf` / `ovabrw_after_sort_cckf`         | Action | Fire before/after drag-drop sort is saved (AJAX).                                                     |
| `ovabrw_before_save_cckf` / `ovabrw_after_save_cckf`         | Action | Fire before/after the popup form Save (wraps add and edit).                                           |
