List Page Customization
The Million Dollar Script list view (the /milliondollarscript/list/ route and the [milliondollarscript type="list"] shortcode) exposes filters that make it easy to add custom columns, modify row data, and control the display layout.
Rendering Overview
The list markup is generated by the MDS Ajax handler. Any filter you attach is applied everywhere the list appears—whether accessed via route, shortcode, or block.
Entry Points
| Hook | Purpose |
|---|---|
mds_list_container_attributes |
Modify wrapper div attributes/classes |
mds_list_wrapper_attributes |
Modify inner wrapper attributes |
mds_list_columns |
Add, remove, or reorder column definitions |
mds_list_heading_cell |
Tweak individual heading cell output |
mds_list_heading_cells |
Modify all heading cells at once |
mds_list_orders_sql |
Customize the SQL query for fetching records |
mds_list_rows |
Filter the rows after fetching from database |
mds_list_row_context |
Alter the data passed to each cell |
mds_list_row_cells |
Modify all cells in a row |
mds_list_cell |
Adjust any cell after rendering |
mds_list_cell_{column_key} |
Adjust a specific column's cell |
mds_list_link_* |
Change advertiser link target, label, or attributes |
mds_list_grid_tracks |
Control CSS Grid column sizing |
mds_list_grid_template |
Replace the final grid-template-columns string |
mds_list_default_grid_tracks |
Override built-in default track sizes |
The generated markup wraps the table in a .mds-list-wrapper div so the list can scroll horizontally on narrow screens without breaking the column layout.
Grid Layout Basics
The list renders as a CSS Grid. Each row inherits a grid-template-columns definition via the CSS custom property --mds-list-grid-template. The default template is derived from the active column definitions and filters, so custom columns automatically participate in the layout.
Key points:
- Provide a
grid_trackkey in your column definition to set an explicit track size (e.g.,'grid_track' => 'minmax(0, 2fr)') - Use
mds_list_default_grid_tracksto override the built-in defaults for standard columns - Use
mds_list_fallback_grid_trackto change the catch-all template applied to additional columns - Filter
mds_list_grid_tracksto inspect or modify the array of tracks before serialization - Filter
mds_list_grid_templateto replace the final space-delimited template string entirely
Banner headings are rendered inside a dedicated .mds-banner-row. They receive a data-column-count attribute and automatically span all grid columns, so the banner name always stretches across the full width regardless of how many columns are active.
Example: Add a Launch Date Column
This example shows how an extension can add a Carbon Fields date field to the advertiser form and display it on the list page.
<?php
/**
* Plugin Name: MDS Launch Date Column
* Description: Adds a launch date field and list column
*/
use Carbon_Fields\Field\Field;
// 1. Add a launch date field to the advertiser form
add_filter('mds_form_fields', function (array $fields, string $prefix) {
$fields[] = Field::make('date', $prefix . 'launch_date', __('Launch Date', 'my-extension'))
->set_help_text(__('Optional: choose when this campaign goes live.', 'my-extension'))
->set_storage_format('Y-m-d');
return $fields;
}, 10, 2);
// 2. Add a new column to the list view
add_filter('mds_list_columns', function (array $columns) {
$columns[] = [
'key' => 'launch_date',
'label' => __('Launch Date', 'my-extension'),
'render_callback' => function (array $row_context) {
$timestamp = strtotime(
carbon_get_post_meta($row_context['ad_id'], MDS_PREFIX . 'launch_date')
);
if (!$timestamp) {
return __('Not set', 'my-extension');
}
return esc_html(date_i18n(get_option('date_format'), $timestamp));
},
'cell_attributes' => ['class' => ['list-cell', 'list-cell--launch-date']],
'heading_attributes' => ['class' => ['list-heading', 'list-heading--launch-date']],
'grid_track' => 'minmax(100px, 1fr)',
];
return $columns;
});
// 3. Optionally decorate future dates with a badge
add_filter('mds_list_cell_launch_date', function (array $cell, array $column, array $row_context) {
$timestamp = strtotime(
carbon_get_post_meta($row_context['ad_id'], MDS_PREFIX . 'launch_date')
);
if ($timestamp && $timestamp > time()) {
$cell['content'] .= ' <span class="mds-badge mds-badge--scheduled">'
. esc_html__('Scheduled', 'my-extension')
. '</span>';
}
return $cell;
}, 10, 3);
The example assumes Carbon Fields is already loaded (it ships with the core plugin). The meta key follows the convention _mds_launch_date thanks to the prefix provided by the filter.
Column Definition Structure
When adding columns via mds_list_columns, each column is an array with these keys:
| Key | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | Unique identifier for the column |
label |
string | Yes | Display text for the heading |
render_callback |
callable | Yes | Function that returns cell content |
cell_attributes |
array | No | HTML attributes for <td> |
heading_attributes |
array | No | HTML attributes for <th> |
grid_track |
string | No | CSS Grid track size (e.g., '1fr', 'minmax(0, 2fr)') |
The render_callback receives a $row_context array containing:
ad_id- The post ID of the advertiser/pixelorder_id- The order IDbanner_id- The banner/grid IDuser_id- The user ID- Additional row data from the database query
Styling Your Columns
The CSS shipped with MDS recognizes class patterns like .list-cell--{key} and .list-heading--{key}. Target these selectors in your extension's CSS for custom styling:
/* Style the launch date column */
.list-cell--launch-date {
font-family: monospace;
color: #666;
}
.list-heading--launch-date {
min-width: 120px;
}
/* Style the scheduled badge */
.mds-badge--scheduled {
background: #e3f2fd;
color: #1976d2;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.85em;
}
When targeting the grid, prefer the provided CSS variables rather than duplicating track definitions:
.mds-container .table-row {
grid-template-columns: var(--mds-list-grid-template);
}
Additional Customization Ideas
Filter Records
Use mds_list_orders_sql to exclude specific order statuses:
add_filter('mds_list_orders_sql', function (string $sql) {
// Only show completed orders
return str_replace(
'WHERE 1=1',
"WHERE 1=1 AND order_status = 'completed'",
$sql
);
});
Customize Banner Headings
Inject custom content into banner rows:
add_filter('mds_list_banner_heading_cell', function (array $cell, int $banner_id) {
$custom_text = get_post_meta($banner_id, '_banner_tagline', true);
if ($custom_text) {
$cell['content'] .= ' <small>(' . esc_html($custom_text) . ')</small>';
}
return $cell;
}, 10, 2);
Replace Advertiser Links
Change the default anchor to a button:
add_filter('mds_list_link_attributes', function (array $attrs, array $row_context) {
$attrs['class'][] = 'button';
$attrs['class'][] = 'button-primary';
return $attrs;
}, 10, 2);
add_filter('mds_list_link_text', function (string $text, array $row_context) {
return __('View Details', 'my-extension');
}, 10, 2);
Reorder Columns
Remove or reorder existing columns:
add_filter('mds_list_columns', function (array $columns) {
// Remove a column by key
$columns = array_filter($columns, function ($col) {
return $col['key'] !== 'unwanted_column';
});
// Reorder: move 'status' to the end
$status_col = null;
foreach ($columns as $i => $col) {
if ($col['key'] === 'status') {
$status_col = $col;
unset($columns[$i]);
break;
}
}
if ($status_col) {
$columns[] = $status_col;
}
return array_values($columns);
});
Best Practices
- Use unique column keys - Prefix with your extension slug to avoid conflicts
- Escape all output - Always use
esc_html(),esc_attr(), etc. - Keep render callbacks fast - Avoid expensive queries; cache if needed
- Test with multiple grids - Ensure columns work when list shows all grids
- Provide sensible defaults - Handle missing data gracefully
- Document your columns - Let site admins know what new columns show
Further Reading
- Hooks Reference - Complete hooks documentation
- Extension Development - Building MDS extensions
- Developer Overview - Getting started with MDS development