Cart-to-Quote for WooCommerce

Our Cart-to-Quote plugin enables customers to convert their shopping cart into a WooCommerce order with a “Pending Quote” status. The store manager can add/amend shipping and adjust prices before switching the order to “Pending Payment”.

Setup and Configuration

The plugin’s settings are located in WooCommerce > Settings > Cart-to-Quote.

Cart-to-Quote for WooCommerce settings tab
The Cart-to-Quote settings tab in WooCommerce

The Cart-to-Quote plugin needs the WooCommerce checkout to be in “classic” mode.

Edit your checkout page in the block editor. If your checkout uses the old-style shortcode, you’re all set. But if you’re using the checkout block, it’s easy to switch between classic and block mode…

Quotes for non-shippable orders

The default out-the-box configuration will show the request-a-quote button only when an cart cannot be shipped. This can be because the customer’s shipping address is in a country you’ve not accounted for. Or it might be because their cart exceeds a certain weight threshold.

Quote options for shippable orders

We can also show a request-a-quote button for carts that meet your site’s shipping requirements. There are several modes of operation:

  • Force all orders to go through a quote stage. This effectively removes the Pay Now button from the checkout.
  • Force all items with a particular shipping class to go through a quote stage, e.g. Shipping Class = “Quoted freight”
  • Let any customers request a quote. Adds the request-a-quote button alongside the Pay Now button, so users can choose to either pay, or request a quote.

Custom checkout quote validation

Sometimes you might want a different set of optional and required fields for a quotes. This requires a small PHP snippet to be added to your checkout page.

This example shows how you can configure the billing phone number to be optional for new orders, but mandatory for new quotes:

/**
 * cart-to-quote-custom-checkout.js
 */
(function($) {
	'use strict';

	/**
	 * Custom validation for new quotes.
	 */
	$(document.body).on('custom_quote_validation', (event, customValidation) => {
		if (!$('#billing_phone').val()) {
			customValidation.isValid = false;
			customValidation.messages.push('Billing phone number is required for quote requests');
		}
	});
})(jQuery);

The customValidation object contains two properties. Set isValid=false to prevent a new quote from being created, and add text messages to messages (an array of string):

{
	"isValid": true,
	"messages: []
}

Emails

Recommended settings

Cart-to-quote recommended email settings
Recommended settings in WooCommerce > Cart-to-Quote

The plugin can send out emails for the following events:

Emails to admins

New quote received (plain)
email-to-admin-about-new-order.php

New quote received (similar ro the WooCommerce New Order email)
email-to-admin-about-new-quote.php

Customer has paid for their quote
email-to-admin-about-paid-for-quote.php

Emails to customers

Thank you for requesting a quote (simple)
email-to-customer-about-new-quote.php

Thank you for requesting a quote (with line items)
email-to-customer-about-new-quote-with-detail.php

Your quote is ready to be paid
email-to-customer-quote-is-ready.php

Your quote is ready to be paid (with line items)
email-to-customer-quote-is-ready-with-detail.php

You have a quote that is waiting to be paid for (reminder)
email-to-customer-quote-reminder.php

If you enable the option to use WooCommerce Email Styles, outbound emails will be wrapped with Woo’s $mailer->wrap_message() function to pick up your store’s email styles.

Use WooCommerce email styles for quotes
Use any WooCommerce email style plugin to change the look & feel of your emails
Quote is ready email
Email to the customer saying their quote is ready to be paid

Custom email signature

The standard email signature that customers will see, looks like this

WooCommerce quote email signature
Standard email signature

You can use a PHP snippet either in your child theme or with a PHP Snippet Manager plugin to override the signature, like this:

function custom_new_quote_email_sign_off_html($html)
{
    $html = '
<p>Thank you for requesting a quote</p>
<p><strong>Kind regards</strong></p>
<p>All the team...</p>
<p>Your Company Name</p>';

    return $html;
}
add_filter('cto_new_quote_email_sign_off_html', 'custom_new_quote_email_sign_off_html', 10, 1);
Custom WooCommerce quote email signature
Custom email signature

Customise email template

To edit the main content of quote-related emails, you will need to copy one of the PHP templates to your child theme and make your modifications. This works exactly the same as editing PHP template snippets from other parts of WooCommerce.

Edit WooCommerce PHP template files

Let’s add some custom order meta to the email that goes to a customer when a quote transitions from “Pending Review” to “Process Payment” (the quote becomes ready for payment):

The source template file is:

/wp-content/plugins/cart-to-order-review/public-templates/emails/email-to-customer-quote-is-ready-with-detail.php

Procedure

This is what we’re going to do…

  1. Create a directory in your site’s child theme called “/woocommerce/emails/”
  2. Copy the source template (PHP) file to the child theme’s “/woocommerce/emails/” directory
  3. Edit the PHP file with your changes
  4. Create a test quote on your site, with your email address set as the billing address
  5. Edit the quote and change its status from “Pending Quote” to “Pending Payment”
  6. Check your email to review the changes

First, go into your site’s child theme and create a directory called “woocommerce” (if it doesn’t already exist). In that folder, create another folder called “emails”. Then copy the file “/wp-content/plugins/cart-to-order-review/public-templates/emails/email-to-customer-quote-is-ready-with-detail.php” into the “woocommerce/emails” folder in your child theme, so your child theme should look something like this:

  • wp-content/
    • my-child-theme/
      • functions.php
      • styles.css
      • woocommerce/
        • emails/
          • email-to-customer-quote-is-ready-with-detail.php

Add some text near the top of the PHP file and inject a custom greeting to the customer:

Add custom text to customer quote email
Add a simple HTML snippet to the customer-facing email

Test the modification by editing your test quote and changing its status from Pending Quote to Pending Payment.

Changelog

Version 1.25.1

Released: 2025-05-29

  • Minor adjustments to the new option that enables a more inclusive element selector when handling required fields on the checkout.

Version 1.25.0

Released: 2025-05-15

  • Fix the "Should the customer be emailed when a quote changes to Pending Payment" issue.
  • Added a new action that's triggered when a quote is paid for: cto_quote_has_been_paid_for
  • Added an option to change the created_via meta for new quotes from "checkout" to "admin". Potentially useful for conversion analytics.
  • Added an option to use a more inclusive element selector when analysing the required fields in the checkout, to fix an issue with Divi on the checkout page.

Version 1.24.2

Released: 2025-03-19

  • Fix a bug when overriding an order's recipient email address - when creating orders manually in the back-end.

Older releases

  • Fixed a potential issue with some plugins that adjust how orders are numbered, when the order number is used instead of the order id.
  • New option to use the WooCommerce Order Number as the quote number (instead of the order id). Useful if you have a plugin that customises your order numbers, e.g. sequential order numbers. This is used in email communications about quotes (to customer & admin). You can also use the PHP filter cto_get_quote_number to customise the quote number.
  • Standardise the signature in customer-facing emails so it can be overridden with a PHP filter.
  • Switch to the customer's locale before sending quote emails, so customers receive emails in their own language (if the language is configured).
  • Add the ability to capture a second (copy-to) email address for quotes on the checkout page. Useful if new quotes need to be sent to an Accounts Payable email address.
  • Add an option to let non-logged-in users (guests) pay for logged-in customer quotes. Useful if your customer has an account on your Woo store and they want to send the quote to accounts payable for payment.
  • Added a new setting so you can override the popup/alert box at the checkout when a new quote has been created. This doesn't apply if the user journey is set to go directly to the newly created quote in the my account area.
  • Added a note to tell WooCommerce that Cart-to-Quote requires the checkout to run in "classic mode". This should help new customers to configure the cart-to-quote workflow easier.
  • Add two new settings so you can copy the billing and/or shipping addresses from new quotes to the customer's existing WP user profile. We will consider making this the default behaviour in a future release.
  • Add a new user-journey option to control what happens when a user creates a new quote at the checkout. They can either see an alert, then be redirected to the My Account / Orders page (view all orders & quotes), or go directly to view their new quote (in My Account / Orders).
  • Added a JS event in the checkout to enable customer JS validation in the browser before a quote request is submitted over Ajax. This is useful if you've got a heavily modified checkout page and the standard DOM element selectors might not work. Documentation for this will follow soon.
  • Added the following actions to email templates so you can inject additional user-facing (or admin-facing) information. All actions take the single parameter $order : cto_new_order_admin_email_before_table, cto_new_order_admin_email_after_table, cto_new_quote_admin_email_before_table, cto_new_quote_admin_email_after_table, cto_new_quote_email_before_order_table, cto_new_quote_email_after_order_table

Add a new option to include shipping and sub-totals in the new/pending quote email to customers. This option only applies if you choose the "Line items listed as a quote" option for the Quote Pending email type.

  • Added three new filters so you can customise the email subject for admin-facing emails, "cto_new_quote_email_to_admin_subject", "cto_quote_ready_email_to_admin_subject" and "cto_quote_paid_email_to_admin_subject"
  • When a quote is requested from the cart page and the user is already logged-in, we now populate the billing and shipping addresses with those stored against the user account (instead of leaving them blank).
  • Fixed a problem that stopped you being able to set the title of the PO gateway in the checkout.
  • Fixed a problem that caused new quotes to be not editable in some situations.
  • The new filter "cto_quote_order_statuses" lets you use a custom order status for quotes that are pending review and quotes that are expired.
  • Added an option to let customers approve/accept their quotes without having to pay for them - so they can go from pending-review to processing. This is useful if your store processes customer payments outside of the WooCommerce payment gateway workflow.
  • Improved templates for "New Quote" and "Quote Is Ready" emails. To use the new emails, go to WooCommerce/Settings/Cart-to-Quote. Then choose "Line items listed as a quote" and "Line items and a link to pay" as your Email Types.
  • Added the cto_before_shipping_quote_button and cto_after_shipping_quote_button actions to make it easy to inject text before/after the Request a Quote button when no shipping is available.
  • Fixed a bug with the new option that can force the quote stage when the cart has a particular shipping-class item in it. The plugin was adding an arbitrary shipping method, instead of leaving the shipping empty.
  • New option to create a Shipping Class that forces a cart to go through the quote stage. Assign your shipping class (e.g. "Quote Shipping") to any products you want to always be quoted, and set the "

Shipping class to quote" option in our plugin.

  • Extended the new option that sends a detailed quote (new order) email (instead of the welcome note email) so it works with quotes that are still at the pending quote/review stage too.
  • Full support for WooCommerce High Performance Order Storage (HPOS).
  • New option to use the "New Order/Quote" email (detail) instead of the welcome message and link. See also the "cto_prefer_woocommerce_invoice_email" bool filter.
  • UI enhancement to the checkout page. When both "Use for All Orders" AND "Can any customer convert their cart into a quote" are enabled, we now suppress the request a bespoke shipping quote button and always use the Convert your Cart into a quote button.
  • Fixed: In some cases, newly created customers were not being assigned to their newly created quotes.
  • Fixed an issue where some guest users were able to request a cart from the checkout page without entering a billing address.
  • Updated the fr-FR translations (machine translated)
  • Updated translations for de-DE and es-ES (machine translated)
  • FIX: The "create account" checkbox on the cart page (quote popup) is now disabled if the WooCommerce option to enable account-creation at the checkout is disabled.
  • New feature: Add a request-a-quote button the cart page.
  • New options on the WooCommerce > Settings > Cart-to-Quote tab for editing the button texts.
  • FIX: Remove scheduled actions when the plugin is deactivated.
  • FIX: The "WooCommerce Email Styles" option should work properly now. It was always-on due to using the wrong wp option.
  • Added an option/action to reactivate a quote. This can be used to reactivate an expired quote, or reset the expiration duration on an existing/open quote. The option is in the Quote Actions meta box when you edit an order.
  • Updated core power-plugins support library to the latest version.
  • Fixed a problem when reporting on the successful manual resending of reminder emails.
  • Added a new email template for quote-reminder emails. If you have reminder emails enabled, it will be used automatically
  • There's also a new meta box when editing an active quote that lets you manually send reminder emails
  • When reminder emails are sent (either automatically or manually) it's now recorded against the order/quote as a note.

To override the contents of the reminder email, copy the file...

wp-content/plugins/cart-to-order-review/public-templates/emails/email-to-customer-quote-reminder.php

...to...

wp-content/yourtheme/woocommerce/emails/email-to-customer-quote-reminder.php

  • Added a new filter so you can replace the "your quote is ready" email with the standard WooCommerce "New Invoice" email. To use this standard WC invoice, return true from the "cto_prefer_woocommerce_invoice_email" filter.
  • Added a new option in WooCommerce > Settings > Cart to Quote so you can choose where to place the "Convert cart into a quote" button in different locations.
  • Fixed a bug where the billing phone number was not always being captured on new quotes.
  • Updated core Power Plugins libraries
  • Added a new option to apply the WooCommerce email templates to customer-facing quote emails.
  • Minor update to remove some diagnostic messages that were popping up in the error logs unnecessarily.
  • Updated the core power-plugins support library.
  • Minor bug fix for logged-in customers who use the "Convert cart to quote" button on the checkout page.
  • Updated Dutch nl_NL translations (machine-translated)
  • Added support for guest checkout, so customers can create quotes without needing to create an account first
  • Better housekeeping to switch expired quotes to a new order-status of "Expired Quote"
  • Updated Power Plugins core library

Minor update to the core Power Plugins support library.

  • New feature. Allow some users (e.g. Store Managers) to create quotes for other customers at the checkout. Add items into your cart, go to the checkout and search for an existing customer... or enter your own billing/shipping details and save the quote against your own account. Great when you've got a sales team who want to create quotes for their clients.
  • Updated Dutch ud83cuddf3ud83cuddf1 translations (machine-translated)

Minor update to fix an edge-case issue similar to that in release 1.4.0. In some cases, a quote that transitioned straight to "pending payment" status wasn't picking up the shipping address. This only affected sites that had custom JavaScript running on the checkout page.

  • New feature : Send out reminder emails before a quote expires. note By default, this feature is not enabled. Go to your WooCommerce Settings > Cart-to-Quote and configure how many days before reminder emails are sent.
  • Fix: There was an edge case that caused the billing and shipping addresses to be blank on new quotes - if there was custom JavaScript in the checkout. This has been resolved.

Fixed a bug with the new automatic quote-to-pending-payment function. If a customer requests a bespoke shipping quote, we need to bypass the automatic jump-to-pending-payment so the store owner can adjust the quote before it is ready for payment.

  • New option to move new quotes straight to the Pending Payment stage, if all the packages can be shipped.
  • New option so customers can send their quotes to a third party, right from their My Account / Orders page. Useful when the customer needs to send a quote to their accounts department to get a PO reference.
  • Added version one of the es_ES translations (machine-translated).
  • Added version one of the it_IT translations (machine-translated).
  • Added version one of the fr_FR translations (machine-translated)
  • Tidied up the emails sent to administrators when new quotes are made and paid for
  • Added version one of de-DE customer-facing translations (machine-translated).
  • Tidied up the customer email templates and added comment-headers to them.
  • Moved public-templates/cart/convert-cart-to-quote-button.php to public-templates/checkout/convert-cart-to-quote-button.php
  • New feature. Enable a button at the checkout so users can request a quote, even if the Pay Now button is available. Configurable and hookable.
  • Added Dutch translations to customer-facing strings

Minor update. Prevent the Mini WP GDPR plugin from enforcing GDPR/Terms acceptance when creating a new user (while creating a quote) at the checkout.

  • Replaced internal template functions with calls to the standard wc_get_template()
  • Tidied some bits-and-bobs. Removed some old/unused code.

Initial public release on Power Plugins.

  • New Feature: Allow certain user roles to convert their cart into a quote at the checkout, for other users. Great for when a shop manager needs to create a quote for a client, and it's easier to use the front end of the website to put together the order. When it gets converted to a quote, you can adjust the order before notifying the customer (adjust the shipping, apply discounts, etc.
  • Partial implementation of the new Purchase Order Payment gateway - to be extended in the next release.
  • Added support for new filters and hooks to better-control special situations in the checkout.
  • Initial release.