Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/dev-sandeep-ghosh/custom-product-page/archive/refs/heads/main.zipNo built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.
Custom Product Page for WooCommerce
A powerful, design-driven plugin that transforms a standard WooCommerce variable product into a dynamic, pixel-perfect product page based on a Figma design. This project was developed to replace the default WooCommerce variable product template with a highly interactive and user-friendly purchasing experience, styled to integrate seamlessly with the Twenty Twenty-Five theme.
Features
- Dynamic Purchase Options: Allows customers to choose between a "Single Drink Subscription" and a "Double Drink Subscription" using a custom radio button interface.
- Interactive Flavor Selection: Beautifully styled flavor selectors that update the product image and are required for purchase. Supports single or multiple flavor selections depending on the chosen subscription.
- Real-Time Dynamic Pricing: Prices and "compare-at" prices update instantly based on user selections.
- Correct Server-Side Pricing: A custom pricing rule (25% subscription discount + 20% sales discount) is correctly applied in the cart and at checkout, preventing any mismatch with the front-end display.
- "What's Included" Section: Dynamically displays the contents of the subscription package, including recurring items and one-time free gifts, managed via a custom meta box on the product edit screen.
- Pixel-Perfect Design: All elements are styled to be a pixel-perfect match of the source Figma design.
- Fully Responsive: The layout seamlessly adapts to tablet and mobile devices for a great user experience on any screen.
- HPOS Compatible: Fully compatible with WooCommerce's High-Performance Order Storage feature.
File Structure
The plugin follows a class-based, object-oriented structure to ensure the code is organized, maintainable, and scalable.
/custom-product-page/
|
|-- custom-product-page.php # Main plugin file (initialization, HPOS declaration)
|-- readme.txt # WordPress.org standard readme file
|-- README.md # Developer-focused documentation (this file)
|
|-- assets/
| |-- css/
| | `-- main.css # All custom CSS and responsive media queries
| `-- js/
| `-- main.js # All JavaScript for UI interactions, AJAX, and price updates
|
|-- includes/
| |-- class-cpp-plugin.php # Main plugin class, loads all other components (Singleton)
| |-- class-cpp-admin.php # Handles the WordPress admin area (custom meta box)
| |-- class-cpp-assets.php # Enqueues and localizes all CSS and JS assets
| |-- class-cpp-cart.php # Handles custom AJAX "Add to Cart" and server-side cart pricing
| `-- class-cpp-templating.php # Manages WooCommerce template overrides
|
|-- templates/
| `-- single-product/
| `-- add-to-cart/
| `-- variable.php # The custom HTML template that replaces the default one
Plugin Flow & Logic
1. Initialization (custom-product-page.php & includes/class-cpp-plugin.php)
- The main
custom-product-page.phpfile defines constants, declares HPOS compatibility using thebefore_woocommerce_inithook, and ensures WooCommerce is active. - It then instantiates the main plugin class,
CPP_Plugin, which acts as a singleton to prevent multiple initializations. - The
CPP_Pluginclass constructor includes all necessary class files and initializes them.
2. Admin Area (includes/class-cpp-admin.php)
- This class uses the
add_meta_boxeshook to register a new meta box titled "What's Included Details" on theproductpost type edit screen. - It uses the
save_post_producthook to save the data entered into these custom fields.
3. Templating (includes/class-cpp-templating.php)
- This class uses the
woocommerce_locate_templatefilter to intercept the request for thevariable.phptemplate. - When WooCommerce tries to load
single-product/add-to-cart/variable.php, the filter hijacks the request and points it to our custom template located at/templates/single-product/add-to-cart/variable.php. This is the core mechanism for replacing the front-end display. - It also uses the
woocommerce_get_price_htmlfilter to hide the default price range on the product page, allowing our custom JavaScript to control the price display exclusively.
4. Asset Loading (includes/class-cpp-assets.php)
- This class uses the
wp_enqueue_scriptsaction to loadmain.cssandmain.jsonly on single product pages (is_product()). - Crucially, it uses
wp_localize_scriptto pass essential dynamic data from PHP to our JavaScript file. This data includes:ajax_url: For making AJAX requests.nonce: For securing AJAX requests.cart_url: The correct, dynamic URL for the cart page.currency_symbol: The store's active currency symbol.
5. Front-End Interaction (assets/js/main.js)
- The JavaScript file listens for all user interactions on the custom template.
- State Management: It maintains a
selectionobject to track the chosen subscription mode (single/double) and the selected flavor variation IDs. - Event Handlers:
changeoninput[name="purchase_option"]: Switches between Single and Double subscription modes, showing/hiding the relevant content.changeon.cpp-flavor input: Updates theselectionobject with the chosen variation ID.submiton the main form: Prevents default form submission.
- Dynamic Pricing: The
updatePriceDisplay()function calculates the final price based on the base price and the hardcoded discount rules (0.75for subscription,0.80for sale) and injects it into the page. - AJAX Add to Cart: On form submission, it gathers the selected variation IDs and sends them to the back end via an AJAX
POSTrequest to thecpp_add_to_cartaction.
6. Custom Cart Logic (includes/class-cpp-cart.php)
- AJAX Handler (
ajax_add_to_cart_handler):- Receives the AJAX request from
main.js. - Verifies the nonce for security.
- Loops through the submitted variation IDs.
- Adds each product to the cart using
WC()->cart->add_to_cart(). - Crucially, it adds custom cart item data (
cpp_subscription_item=>true) to each item. This "tags" the item as one that needs special pricing.
- Receives the AJAX request from
- Server-Side Pricing (
apply_custom_subscription_pricing):- This function hooks into
woocommerce_before_calculate_totals, which runs every time the cart is calculated. - It iterates through every item in the cart.
- If an item has the
cpp_subscription_itemmeta data, it ignores any price set in WooCommerce and calculates the price from scratch based on the product's regular price and the25% + 20%discount rule. - It then uses
$product->set_price()to apply this final, correct price to the cart item. This ensures the price is correct everywhere—in the mini cart, on the cart page, and at checkout.
- This function hooks into
How to Set Up
To test this plugin, you must configure a product correctly:
- Create a Variable Product: Go to Products > Add New and select "Variable product".
- Add
FlavorAttribute: In the Attributes tab, add aFlavorattribute with values likeChocolate | Vanilla | Orange. Check the "Used for variations" box. - Create Variations: Go to the Variations tab and create variations from all attributes.
- Set Price and Image: For each variation, set a Regular Price and upload a unique image.
- Fill Custom Fields: Use the "What's Included Details" box to add descriptive text for each subscription type.
- Publish the product and view it on the front end.