Theme Integration Guide
Customize WP Sell Services appearance to match your WordPress theme through template overrides, CSS customization, and template hooks.
Template Override System
Section titled “Template Override System”The plugin uses TemplateLoader (src/Frontend/TemplateLoader.php) to load templates with theme override support. When a template is requested, the loader checks locations in this order:
- Child theme:
wp-content/themes/child-theme/wp-sell-services/{template}.php - Parent theme:
wp-content/themes/parent-theme/wp-sell-services/{template}.php - Plugin default:
wp-content/plugins/wp-sell-services/templates/{template}.php
Setting Up Overrides
Section titled “Setting Up Overrides”- Create
wp-sell-services/directory in your theme - Copy the template you want to customize from
wp-sell-services/templates/ - Edit the copied file in your theme directory
- Clear page cache and refresh
Only copy templates you need to change. Uncopied templates continue using plugin defaults.
Available Templates
Section titled “Available Templates”Top-Level Templates
Section titled “Top-Level Templates”| Template | Purpose |
|---|---|
single-service.php |
Single service page |
archive-service.php |
Service archive/listing page |
single-request.php |
Single buyer request page |
archive-request.php |
Buyer request archive page |
content-service-card.php |
Service card in grids and listings |
content-request-card.php |
Buyer request card in listings |
content-no-services.php |
Empty state when no services found |
content-no-requests.php |
Empty state when no requests found |
Partial Templates (templates/partials/)
Section titled “Partial Templates (templates/partials/)”| Template | Purpose |
|---|---|
partials/service-gallery.php |
Image gallery on single service page |
partials/service-packages.php |
Pricing packages (Basic/Standard/Premium) |
partials/service-reviews.php |
Reviews section on single service page |
partials/service-faqs.php |
FAQ accordion on single service page |
partials/vendor-card.php |
Vendor info card on service page sidebar |
partials/vendor-portfolio.php |
Public vendor portfolio lightbox and grid |
Order Templates (templates/order/)
Section titled “Order Templates (templates/order/)”| Template | Purpose |
|---|---|
order/order-view.php |
Order details page |
order/order-requirements.php |
Requirements submission page |
order/order-confirmation.php |
Order confirmation/thank you page |
order/requirements-form.php |
Requirements form template |
order/conversation.php |
Order messaging/conversation view |
Order URLs route as: /service-order/{id}/ (view), /service-order/{id}/requirements/, /service-order/{id}/delivery/, /service-order/{id}/review/.
Dashboard Templates (templates/dashboard/sections/)
Section titled “Dashboard Templates (templates/dashboard/sections/)”| Template | Purpose |
|---|---|
dashboard/sections/orders.php |
Orders section |
dashboard/sections/sales.php |
Sales section (vendor) |
dashboard/sections/services.php |
Services management |
dashboard/sections/earnings.php |
Earnings section |
dashboard/sections/messages.php |
Messages section |
dashboard/sections/profile.php |
Profile editing |
dashboard/sections/requests.php |
Buyer requests |
dashboard/sections/create.php |
Service creation |
dashboard/sections/create-request.php |
Buyer request creation |
dashboard/sections/edit-request.php |
Edit an existing buyer request |
WooCommerce Account Templates (templates/myaccount/)
Section titled “WooCommerce Account Templates (templates/myaccount/)”| Template | Purpose |
|---|---|
myaccount/service-orders.php |
Service orders in WooCommerce My Account |
myaccount/vendor-dashboard.php |
Vendor dashboard in My Account |
myaccount/vendor-services.php |
Vendor services list |
myaccount/service-disputes.php |
Disputes tab |
myaccount/notifications.php |
Notifications tab |
Cart Templates (templates/cart/)
Section titled “Cart Templates (templates/cart/)”| Template | Purpose |
|---|---|
cart/cart.php |
Shopping cart page for standalone checkout mode |
Other Templates
Section titled “Other Templates”- Vendor:
vendor/profile.php– Public vendor profile page (served at/provider/{username}/by default, customizable via thewpss_vendor_slugfilter) - Disputes:
disputes/dispute-view.php– Dispute details view
Email Templates (templates/emails/)
Section titled “Email Templates (templates/emails/)”All email templates are theme-overridable at yourtheme/wp-sell-services/emails/.
26 HTML templates:
| Template | Purpose |
|---|---|
emails/new-order.php |
New order notification |
emails/order-in-progress.php |
Vendor started work |
emails/delivery-ready.php |
Delivery submitted for review |
emails/order-completed.php |
Order completed |
emails/order-cancelled.php |
Order cancelled |
emails/requirements-submitted.php |
Buyer submitted requirements |
emails/requirements-reminder.php |
Reminder to submit requirements |
emails/revision-requested.php |
Buyer requested revision |
emails/cancellation-requested.php |
Cancellation request filed |
emails/new-message.php |
New order message |
emails/dispute-opened.php |
Dispute opened |
emails/dispute-escalated.php |
Dispute escalated to admin |
emails/seller-level-promotion.php |
Vendor promoted to new seller level |
emails/moderation-pending.php |
Service submitted for moderation |
emails/moderation-approved.php |
Service approved |
emails/moderation-rejected.php |
Service rejected |
emails/moderation-response.php |
Vendor responded to moderation feedback |
emails/vendor-contact.php |
Vendor contact form submission |
emails/withdrawal-requested.php |
Vendor requested withdrawal |
emails/withdrawal-approved.php |
Withdrawal approved |
emails/withdrawal-rejected.php |
Withdrawal rejected |
emails/withdrawal-auto.php |
Automatic withdrawal processed |
emails/generic.php |
Generic notification template |
emails/test-email.php |
Test email (from settings) |
emails/email-header.php |
Shared email header with logo and branding |
emails/email-footer.php |
Shared email footer |
10 plain text variants at emails/plain/:
| Template | Purpose |
|---|---|
emails/plain/new-order.php |
Plain text new order |
emails/plain/order-in-progress.php |
Plain text order started |
emails/plain/order-completed.php |
Plain text order completed |
emails/plain/order-cancelled.php |
Plain text order cancelled |
emails/plain/delivery-ready.php |
Plain text delivery submitted |
emails/plain/requirements-submitted.php |
Plain text requirements submitted |
emails/plain/requirements-reminder.php |
Plain text requirements reminder |
emails/plain/revision-requested.php |
Plain text revision requested |
emails/plain/new-message.php |
Plain text new message |
emails/plain/dispute-opened.php |
Plain text dispute opened |
See Email Customization for how to override email content, headers, footers, and sender details using filters.
Template Functions
Section titled “Template Functions”// Load a template part (like WP get_template_part but with plugin fallback)wpss_get_template_part( 'content', 'service-card' );// Searches: theme/wp-sell-services/content-service-card.php then plugin/templates/
// With argumentswpss_get_template_part( 'partials/vendor-card', '', [ 'vendor_id' => 42 ] );
// Load a specific template filewpss_get_template( 'order/order-view.php', [ 'order' => $order ] );Template Filters
Section titled “Template Filters”// Redirect template loading without copying filesadd_filter( 'wpss_locate_template', function( $template, $template_name, $template_path ) { if ( 'single-service.php' === $template_name ) { return '/path/to/my/custom-single-service.php'; } return $template;}, 10, 3 );
// Override a dashboard section templateadd_filter( 'wpss_dashboard_section_template', function( $template_path, $section ) { if ( 'earnings' === $section ) { return get_stylesheet_directory() . '/my-earnings-template.php'; } return $template_path;}, 10, 2 );Single Service Page Hooks
Section titled “Single Service Page Hooks”The SingleServiceView class (src/Frontend/SingleServiceView.php) renders each section via action hooks. You can add, remove, or reorder sections without overriding the entire template.
Default Hook Registration
Section titled “Default Hook Registration”| Hook | Callback | Priority |
|---|---|---|
wpss_single_service_header |
render_breadcrumb |
5 |
wpss_single_service_header |
render_title |
10 |
wpss_single_service_header |
render_meta |
15 |
wpss_single_service_gallery |
render_gallery |
10 |
wpss_single_service_content |
render_description |
10 |
wpss_single_service_content |
render_about_vendor |
20 |
wpss_single_service_faqs |
render_faqs |
10 |
wpss_single_service_reviews |
render_reviews |
10 |
wpss_single_service_sidebar |
render_packages |
10 |
wpss_single_service_sidebar |
render_vendor_card |
20 |
wpss_single_service_related |
render_related_services |
10 |
wpss_after_single_service |
render_order_modal |
10 |
wpss_after_single_service |
render_contact_modal |
20 |
Customizing Sections
Section titled “Customizing Sections”// Add content after service title (priority 12 = after title at 10, before meta at 15)add_action( 'wpss_single_service_header', function( $service ) { if ( get_post_meta( $service->id, '_wpss_featured', true ) ) { echo '<span class="wpss-featured-badge">Featured</span>'; }}, 12 );
// Remove FAQ sectionremove_action( 'wpss_single_service_faqs', [ wpss()->get_single_service_view(), 'render_faqs' ], 10 );
// Show vendor card before packages (move from priority 20 to 5)$view = wpss()->get_single_service_view();remove_action( 'wpss_single_service_sidebar', [ $view, 'render_vendor_card' ], 20 );add_action( 'wpss_single_service_sidebar', [ $view, 'render_vendor_card' ], 5 );Dashboard Customization
Section titled “Dashboard Customization”// Control section accessadd_filter( 'wpss_can_access_dashboard_section', function( $allowed, $section, $user_id ) { if ( 'earnings' === $section ) { return (bool) get_user_meta( $user_id, '_wpss_vendor_verified', true ); } return $allowed;}, 10, 3 );
// Add custom dashboard sectionsadd_filter( 'wpss_dashboard_sections', function( $sections, $user_id, $is_vendor ) { if ( $is_vendor ) { $sections['analytics'] = [ 'label' => 'Analytics', 'icon' => 'chart' ]; } return $sections;}, 10, 3 );
// Rename section titlesadd_filter( 'wpss_dashboard_section_titles', function( $titles ) { $titles['orders'] = 'My Purchases'; $titles['sales'] = 'My Sales'; return $titles;} );Full-width Plugin Pages
Section titled “Full-width Plugin Pages”Since 1.2.0, the plugin’s app-like pages — Dashboard, Cart, Checkout, and Become a Vendor — render full-width without a theme sidebar. This prevents marketplace UI from appearing next to widgets such as Recent Posts.
How it works per theme
Section titled “How it works per theme”The plugin detects the active theme and uses its native mechanism rather than hiding the sidebar with CSS:
| Theme | Method |
|---|---|
| Reign | Sets Reign’s native per-page layout meta (reign_wbcom_metabox_data), the same mechanism Reign uses for FluentCart. Reign’s page wrappers and subheader remain intact. |
| BuddyX / BuddyX Pro | Uses the theme’s bundled “Page No Sidebar” template (page-templates/full-width-container.php). |
| Any other theme | Falls back to templates/wpss-fullwidth-template.php, which calls get_header() / get_footer() and emits a contained full-width wrapper. |
If a site owner has already set a specific Page Template on a plugin page in the editor, that choice wins and the plugin does not override it.
Customizing the fallback template
Section titled “Customizing the fallback template”Copy templates/wpss-fullwidth-template.php into your theme to override the fallback wrapper:
yourtheme/wp-sell-services/wpss-fullwidth-template.phpOpting out and controlling scope
Section titled “Opting out and controlling scope”Turn off full-width handling entirely — the active theme’s normal sidebar layout will be used on all plugin pages:
add_filter( 'wpss_use_fullwidth_template', '__return_false' );Control which plugin pages receive the full-width treatment (default: dashboard, cart, checkout, become_vendor):
// Remove the dashboard from full-width treatmentadd_filter( 'wpss_fullwidth_page_keys', function( $keys ) { return array_diff( $keys, [ 'dashboard' ] );} );See also wpss_use_fullwidth_template and wpss_fullwidth_page_keys in the hooks reference.
CSS Classes Reference
Section titled “CSS Classes Reference”The plugin uses wpss- prefixed CSS classes. Verified classes from SingleServiceView.php:
.wpss-breadcrumb / .wpss-breadcrumb-list / .wpss-breadcrumb-item / .wpss-breadcrumb-current.wpss-service-title / .wpss-service-meta / .wpss-meta-item.wpss-meta-vendor / .wpss-meta-rating / .wpss-meta-orders / .wpss-meta-queue.wpss-vendor-mini-avatar / .wpss-vendor-name / .wpss-verified-badge.wpss-rating-link / .wpss-rating-value / .wpss-rating-count.wpss-star / .wpss-star.filledEnqueued Stylesheets
Section titled “Enqueued Stylesheets”| Handle | File | Purpose |
|---|---|---|
wpss-design-system |
assets/css/design-system.css |
CSS custom properties and tokens |
wpss-frontend |
assets/css/frontend.css |
Base frontend styles |
wpss-single-service |
assets/css/single-service.css |
Single service page |
wpss-unified-dashboard |
assets/css/unified-dashboard.css |
Dashboard styles |
Overriding Styles
Section titled “Overriding Styles”// Enqueue a custom stylesheet after plugin stylesadd_action( 'wp_enqueue_scripts', function() { wp_enqueue_style( 'mytheme-wpss', get_stylesheet_directory_uri() . '/css/wpss-custom.css', [ 'wpss-frontend' ], '1.0.0' );}, 20 );
// Or dequeue plugin styles entirelyadd_action( 'wp_enqueue_scripts', function() { wp_dequeue_style( 'wpss-frontend' ); wp_deregister_style( 'wpss-frontend' );}, 100 );Dark Mode and Design Tokens
Section titled “Dark Mode and Design Tokens”Added in 1.3.0. Every plugin surface is built on CSS custom-property tokens in design-system.css, and the plugin follows the active theme’s dark mode rather than the OS preference. This means WP Sell Services goes dark exactly when the theme does, and never darkens on top of a light theme.
How dark mode is triggered
Section titled “How dark mode is triggered”The plugin’s dark tokens activate when any of these signals is present on the root element — the same signals BuddyX, BuddyX Pro, and Reign 8.x already set from their own dark-mode toggle:
:root[data-theme="dark"],:root[data-bx-mode="dark"],.wpss-dark .wpss-app { /* dark token overrides */ }If your theme has a dark toggle, set data-bx-mode="dark" (or data-theme="dark") on <html> and the plugin follows automatically — no per-component CSS required. There is deliberately no prefers-color-scheme rule, so the plugin never fights a light theme on a dark OS.
Token model
Section titled “Token model”Components consume semantic and scale tokens, never raw hex. In dark mode the whole system flips in one place:
| Token group | Light | Dark | Used for |
|---|---|---|---|
--wpss-surface |
#ffffff |
#1f2937 |
Card / panel backgrounds |
--wpss-text / --wpss-text-muted |
dark | light | Body + muted copy |
--wpss-gray-* ramp |
light ramp | inverted ramp | Raw text + hairlines (ink end resolves light, paper end dark) |
--wpss-primary |
#4f46e5 |
#4f46e5 |
Button/badge fills (stays dark enough for white text) |
--wpss-primary-accent |
#4f46e5 |
#a5b4fc |
Primary as text/links/icons (lightens on dark) |
--wpss-secondary-accent |
#1e293b |
#e2e8f0 |
Emphasis text (prices) |
--wpss-block-surface |
var(--wpss-surface) |
flips | Gutenberg block card backgrounds |
Two rules matter when extending the UI:
- Use
--wpss-primary-accent/--wpss-secondary-accentfor text,--wpss-primary/--wpss-secondaryfor fills. The accent tokens lighten in dark mode so links stay readable on dark surfaces; the fill tokens stay dark so white button text keeps its contrast. - Never hard-code hex for text or surfaces — reach for the tokens above so your addition flips with the rest of the plugin. Lucide icons inherit
currentColor, so they follow the text token automatically.
Overriding tokens per theme
Section titled “Overriding tokens per theme”Redefine any token under your theme’s dark selector to match your palette exactly:
html[data-bx-mode="dark"] { --wpss-surface: #12141a; /* match your theme's card colour */ --wpss-primary-accent: #93c5fd;}JavaScript Integration
Section titled “JavaScript Integration”| Handle | File | Dependencies |
|---|---|---|
alpinejs |
assets/js/vendor/alpine.min.js |
None (defer) |
wpss-frontend |
assets/js/frontend.js |
alpinejs |
wpss-single-service |
assets/js/single-service.js |
jquery, wpss-frontend |
wpss-unified-dashboard |
assets/js/unified-dashboard.js |
jquery |
JavaScript Data Objects
Section titled “JavaScript Data Objects”wpss: ajaxUrl, restUrl, nonce
wpssData: ajaxUrl, apiUrl, nonce, orderNonce, restNonce, pollingInterval (10000ms), currencyFormat, i18n
wpssService (single service page only): serviceId, ajaxUrl, nonce, checkoutUrl, cartUrl, i18n
// Add custom scripts after plugin JSadd_action( 'wp_enqueue_scripts', function() { wp_enqueue_script( 'mytheme-wpss-js', get_stylesheet_directory_uri() . '/js/wpss-custom.js', [ 'wpss-frontend' ], '1.0.0', true );}, 20 );URL Structure
Section titled “URL Structure”| Pattern | Template | Filter |
|---|---|---|
/provider/{username}/ |
vendor/profile.php |
wpss_vendor_slug |
/service-order/{id}/ |
order/order-view.php |
wpss_service_order_slug |
/service-order/{id}/{action}/ |
order/order-{action}.php |
wpss_service_order_slug |
/service/ (CPT slug) |
archive-service.php |
wpss_service_slug |
/buyer-request/ (CPT slug) |
archive-request.php |
wpss_buyer_request_slug |
/service-checkout/{id}/ |
Checkout shortcode | wpss_checkout_slug |
All URL slugs are filterable to avoid conflicts with other plugins. After changing slugs, flush rewrite rules by visiting Settings > Permalinks and clicking Save.
Related Documentation
Section titled “Related Documentation”- Hooks and Filters - Complete hooks reference with parameters
- Custom Integrations - Building adapters and extending the API
- REST API - API endpoints for frontend integration

