How to create a custom WooCommerce product type from scratch?

So, you want to create a custom WooCommerce product type from scratch? Great! The quickest answer is that you’ll need to use custom code, specifically by hooking into WooCommerce’s actions and filters to register your new product type and define its unique behaviors. This isn’t something you can do with a simple plugin or theme option without getting your hands a little dirty with PHP.

Why Bother with a Custom Product Type?

Before we dive into the nitty-gritty, let’s touch on why you might even consider this. WooCommerce out-of-the-box offers various product types: Simple, Grouped, External/Affiliate, and Variable. For many shops, these are perfectly adequate. But what if your product doesn’t fit neatly into these categories?

Imagine you’re selling digital subscriptions that expire after a certain number of downloads, or perhaps a service that requires a specific booking slot and then triggers a follow-up task. Or maybe you’re building an e-commerce site for a rental business where each product has a “return date” associated with it. In these cases, a simple “virtual” or “downloadable” product won’t cut it. You need custom fields, custom pricing logic, or entirely different fulfillment processes. That’s where a custom product type shines – it allows you to encapsulate all these unique characteristics and functionalities under a single, well-defined umbrella within your WooCommerce store. Think of it as creating a whole new framework for how a specific type of product behaves and is managed.

Before you write a single line of code, it’s crucial to have a proper development environment. Working directly on a live site is a recipe for disaster.

Local Development Tools

You’ll want a local server setup. Options like Local by Flywheel, DesktopServer, XAMPP, WAMP, or MAMP are excellent for this. They create a local WordPress installation on your computer, allowing you to test changes without impacting your live site. Choose one you’re comfortable with and get a fresh WordPress installation running.

Child Theme or Custom Plugin?

When adding custom code, never modify core WooCommerce files directly, and ideally, avoid modifying your parent theme unless you’re absolutely sure what you’re doing.

  • Child Theme: If your custom product type is very specific to your theme’s functionality or design, a child theme’s functions.php file is a decent place for your code.
  • Custom Plugin: For more complex or reusable custom product types, a custom plugin is the best approach. This keeps your functionality separate from your theme, making it portable and easier to manage updates. For this guide, we’ll generally assume a custom plugin approach for modularity, but the code snippets themselves can be adapted for a child theme’s functions.php.

To create a basic custom plugin, simply create a new folder in wp-content/plugins/ (e.g., my-custom-product-type). Inside that, create a PHP file (e.g., my-custom-product-type.php) and add the standard plugin header:

“`php

/*

Plugin Name: My Custom Product Type

Plugin URI: https://yourwebsite.com

Description: Adds a custom product type to WooCommerce.

Version: 1.0.0

Author: Your Name

Author URI: https://yourwebsite.com

License: GPL2

License URI: https://www.gnu.org/licenses/gpl-2.0.html

Text Domain: my-custom-product-type

*/

// Exit if accessed directly

if ( ! defined( ‘ABSPATH’ ) ) {

exit;

}

“`

Activate this plugin from your WordPress admin dashboard. Now you have a safe place to put all your custom code.

If you’re looking to enhance your WooCommerce store by creating a custom product type from scratch, you might also find it beneficial to explore how to optimize your website’s performance. A related article that can help you improve your site’s speed and user experience is available at Google PageSpeed Insights. This resource provides valuable insights and tips on how to boost your website’s loading times, which can ultimately lead to higher conversion rates and a better overall shopping experience for your customers.

Registering Your Custom Product Type

The first step is to tell WooCommerce that a new product type exists. This involves adding your type to the list that appears when you edit or create a product.

The product_type_selector Filter

WooCommerce uses the product_type_selector filter to populate the dropdown menu for product types in the product data meta box. We’ll hook into this.

“`php

function my_custom_product_type_add_type( $types ) {

$types[ ‘rental’ ] = __( ‘Rental Product’, ‘my-custom-product-type’ );

return $types;

}

add_filter( ‘product_type_selector’, ‘my_custom_product_type_add_type’ );

“`

Let’s break this down:

  • $types is an array of existing product types.
  • We’re adding a new key 'rental' with the value 'Rental Product'. The key is your internal identifier for this product type, and the value is what users will see in the dropdown.
  • __('Rental Product', 'my-custom-product-type') is for text translation, good practice for any translatable string.

After adding this code to your plugin file (or child theme’s functions.php) and activating it, head over to your WordPress admin, go to Products > Add New, and scroll down to the “Product data” meta box. Expand the “Product Type” dropdown, and you should now see “Rental Product” as an option!

Declaring Your Product Class

WooCommerce expects each product type to have a corresponding PHP class. Even if you don’t implement a lot of custom logic in this class yet, it’s essential for WooCommerce to recognize and handle your product type correctly. This class should extend the WC_Product class.

First, let’s include the file where our class will live. It’s good practice to keep classes in a separate file.

“`php

add_action( ‘plugins_loaded’, ‘my_custom_product_type_load_class’ );

function my_custom_product_type_load_class() {

if ( class_exists( ‘WC_Product’ ) ) {

require_once( ‘class-wc-product-rental.php’ );

}

}

“`

Now, create a new file named class-wc-product-rental.php in your plugin directory (the same place as my-custom-product-type.php). Inside this new file, put the following basic class structure:

“`php

// class-wc-product-rental.php

if ( ! defined( ‘ABSPATH’ ) ) {

exit; // Exit if accessed directly

}

/**

  • WC_Product_Rental class.

*/

class WC_Product_Rental extends WC_Product {

/**

  • __construct function.

*

  • @param WC_Product|int $product Product ID or product object.

*/

public function __construct( $product ) {

$this->product_type = ‘rental’;

parent::__construct( $product );

}

/**

  • Get the product type for WooCommerce.

*

  • @return string

*/

public function get_type() {

return ‘rental’;

}

}

“`

Here’s what’s happening:

  • class WC_Product_Rental extends WC_Product: This line tells PHP that our WC_Product_Rental class inherits all the properties and methods from the standard WC_Product class. This is crucial for WooCommerce to interact with your custom product type like any other.
  • $this->product_type = 'rental';: In the constructor, we explicitly set the product_type property to our identifier. This is how WooCommerce internally distinguishes your product.
  • public function get_type(): This method is required by WooCommerce. It should return the string identifier for your product type.

Now, WooCommerce knows about your ‘rental’ type and has a class to associate with it.

Customizing The Product Data Meta Box (Admin)

When you select your custom product type in the dropdown, by default, the product data meta box (where you set price, inventory, shipping, etc.) might look a bit off or completely empty. You’ll want to hide irrelevant tabs and add your own custom fields.

Hiding Unwanted Tabs

WooCommerce allows you to hide certain product data tabs using the woocommerce_product_data_tabs filter. This prevents confusion and keeps the interface clean for your custom product type.

“`php

function my_custom_product_type_hide_tabs( $tabs ) {

// Check if the current product type is ‘rental’

if ( isset( $_GET[‘product_type’] ) && ‘rental’ === $_GET[‘product_type’] ) {

// You might need to check if the posted product type was recently switched via AJAX too.

// For simplicity, we’ll focus on the initial GET param.

// Remove tabs that don’t apply to rental products.

unset( $tabs[‘shipping’] ); // Rental products might not ship in the traditional sense

unset( $tabs[‘attribute’] ); // Maybe attributes aren’t relevant for you

// unset( $tabs[‘linked_product’] );

// unset( $tabs[‘advanced’] );

// You get the idea. Be selective about what you keep.

}

return $tabs;

}

add_filter( ‘woocommerce_product_data_tabs’, ‘my_custom_product_type_hide_tabs’, 10, 1 );

“`

Remember to add this to your main plugin file. Adjust the unset() calls based on which tabs are irrelevant for your specific custom product type.

Adding Custom Tabs and Fields

This is where you define the unique configuration options for your custom product.

Registering a Custom Tab

First, let’s create a new tab for “Rental Details”.

“`php

function my_custom_product_type_add_rental_tab( $product_data_tabs ) {

$product_data_tabs[‘rental_product_tab’] = array(

‘label’ => __( ‘Rental Details’, ‘my-custom-product-type’ ),

‘target’ => ‘rental_product_data’, // HTML ID for the content div

‘class’ => array( ‘hide_if_variable’, ‘hide_if_grouped’, ‘hide_if_external’, ‘hide_if_simple’ ), // Show only for custom type

‘priority’ => 21, // Adjust priority to position the tab

);

return $product_data_tabs;

}

add_filter( ‘woocommerce_product_data_tabs’, ‘my_custom_product_type_add_rental_tab’ );

“`

Notice the 'class' assignment: array( 'hide_if_variable', 'hide_if_grouped', 'hide_if_external', 'hide_if_simple' ). This is a clever way to tell WooCommerce to only show this tab if none of those standard product types are selected. This, combined with our Javascript trick below, ensures our tab appears for our custom type.

Displaying Tab Content (Custom Fields)

Now we need to add the actual fields into the content area for our new tab. WooCommerce makes this easy with specific actions.

“`php

function my_custom_product_type_display_rental_tab_content() {

global $post;

// Note the target ID from above: ‘rental_product_data’

echo ‘

‘;

// Example 1: Text field for Rental Duration

woocommerce_wp_text_input(

array(

‘id’ => ‘_rental_duration’,

‘value’ => get_post_meta( $post->ID, ‘_rental_duration’, true ),

‘label’ => __( ‘Rental Duration’, ‘my-custom-product-type’ ),

‘placeholder’ => __( ‘e.g., 7 days’, ‘my-custom-product-type’ ),

‘desc_tip’ => ‘true’,

‘description’ => __( ‘Enter the standard rental duration for this product.’, ‘my-custom-product-type’ ),

‘type’ => ‘text’,

‘data_type’ => ‘text’, // important for JS validation if needed

)

);

// Example 2: Checkbox for Requires Deposit

woocommerce_wp_checkbox(

array(

‘id’ => ‘_rental_requires_deposit’,

‘value’ => get_post_meta( $post->ID, ‘_rental_requires_deposit’, true ),

‘label’ => __( ‘Requires Deposit?’, ‘my-custom-product-type’ ),

‘description’ => __( ‘Tick this box if a deposit is required for this rental.’, ‘my-custom-product-type’ ),

)

);

// You can add more fields here like:

// woocommerce_wp_select()

// woocommerce_wp_textarea_input()

// woocommerce_wp_price_input() (for deposit amount maybe)

echo ‘

‘; // close the panel

}

add_action( ‘woocommerce_product_data_panels’, ‘my_custom_product_type_display_rental_tab_content’ );

“`

This code adds two fields: a text input for duration and a checkbox for a deposit. woocommerce_wp_text_input, woocommerce_wp_checkbox, etc., are helper functions provided by WooCommerce to easily create standard input fields.

Saving Custom Field Data

Once you have your fields, you need to save the data when the product is updated.

“`php

function my_custom_product_type_save_rental_tab_data( $post_id ) {

// Save Rental Duration

$rental_duration = isset( $_POST[‘_rental_duration’] ) ? sanitize_text_field( $_POST[‘_rental_duration’] ) : ”;

update_post_meta( $post_id, ‘_rental_duration’, $rental_duration );

// Save Requires Deposit

$requires_deposit = isset( $_POST[‘_rental_requires_deposit’] ) ? ‘yes’ : ‘no’;

update_post_meta( $post_id, ‘_rental_requires_deposit’, $requires_deposit );

}

add_action( ‘woocommerce_process_product_meta_rental’, ‘my_custom_product_type_save_rental_tab_data’ );

“`

The action woocommerce_process_product_meta_{YOUR_PRODUCT_TYPE} is specifically designed for saving data relevant to your custom product type. This is very convenient. sanitize_text_field() is used for sanitization, which is always important.

Adjusting Product Data visibility with JavaScript

By default, even if you add your tab and its content, it won’t appear when you select “Rental Product” because WooCommerce’s existing JS hides all other panels. We need to tell it to show ours and hide others when our custom type is picked.

Create a new file admin-scripts.js in your plugin folder:

“`javascript

jQuery( document ).ready( function( $ ) {

// Show/hide product type specific options

$( ‘select#product-type’ ).change( function() {

var select_val = $( this ).val();

if ( select_val === ‘rental’ ) {

$( ‘.options_group.pricing’ ).addClass( ‘show_if_rental’ ).show(); // Show pricing for us if needed

$( ‘.rental_product_tab’ ).show(); // Show our custom tab

} else {

$( ‘.options_group.pricing’ ).removeClass( ‘show_if_rental’ ).hide(); // Hide if not ours

$( ‘.rental_product_tab’ ).hide(); // Hide our custom tab

}

}).change(); // Run on page load

});

“`

And enqueue this script in your plugin:

“`php

function my_custom_product_type_admin_scripts() {

global $typenow;

if ( ‘product’ === $typenow ) {

wp_enqueue_script(

‘my-custom-product-type-admin’,

plugins_url( ‘admin-scripts.js’, __FILE__ ),

array( ‘jquery’ ),

‘1.0.0’,

true

);

}

}

add_action( ‘admin_enqueue_scripts’, ‘my_custom_product_type_admin_scripts’ );

“`

This JS snippet essentially says: “When the product type dropdown changes to ‘rental’, show specific general groups (like pricing) and our custom tab. Otherwise, hide them.” The show_if_rental class doesn’t exist by default, but it’s a pattern WooCommerce uses, and by applying it, it helps in showing the general tabs we want to keep while our product type is active. Make sure to check the class names depending on which regular sections you wish to keep visible.

Displaying Custom Data on the Frontend

Having the data in the backend is great, but customers need to see it too.

Hooking into Product Page Templates

WooCommerce provides hooks to insert content into various parts of the single product page.

“`php

function my_custom_product_type_display_rental_info_frontend() {

global $product;

// Ensure it’s our custom product type

if ( ‘rental’ === $product->get_type() ) {

$rental_duration = $product->get_meta( ‘_rental_duration’, true );

$requires_deposit = $product->get_meta( ‘_rental_requires_deposit’, true );

if ( ! empty( $rental_duration ) || $requires_deposit === ‘yes’ ) {

echo ‘

‘;

if ( ! empty( $rental_duration ) ) {

echo ‘

‘ . __( ‘Rental Duration:’, ‘my-custom-product-type’ ) . ‘ ‘ . esc_html( $rental_duration ) . ‘

‘;

}

if ( $requires_deposit === ‘yes’ ) {

echo ‘

‘ . __( ‘A deposit is required for this rental.’, ‘my-custom-product-type’ ) . ‘

‘;

}

echo ‘

‘;

}

}

}

add_action( ‘woocommerce_single_product_summary’, ‘my_custom_product_type_display_rental_info_frontend’, 25 ); // Adjust priority

“`

Here, we’re using woocommerce_single_product_summary as a hook, which places our content before the product description but after the price/add-to-cart. We retrieve the data using $product->get_meta() which is the correct way to get post meta from a WC_Product object, and then display it. esc_html() is used for output sanitization.

Overriding Templates (Advanced)

For more extensive frontend changes, you might need to override WooCommerce templates. This involves copying the relevant template file (e.g., single-product/add-to-cart/simple.php) from wp-content/plugins/woocommerce/templates/ into your theme’s woocommerce/ folder, and then adding conditional logic based on $product->get_type(). This grants complete control over the markup.

For our custom product type, we might want a different “Add to cart” button or even an entirely different section. You could create a template file like single-product/add-to-cart/rental.php and then use the woocommerce_loop_add_to_cart_link filter or woocommerce_product_add_to_cart_template to point to your custom template when the product type is ‘rental’.

“`php

// Example for overriding add-to-cart button for loop

function my_custom_product_type_loop_add_to_cart_link( $html, $product ) {

if ( ‘rental’ === $product->get_type() ) {

$html = sprintf(

%s‘,

esc_url( $product->add_to_cart_url() ),

esc_attr( $product->get_id() ),

esc_attr( $product->get_sku() ),

esc_attr( isset( $quantity ) ? $quantity : 1 ),

$product->is_purchasable() ? ‘add_to_cart_button’ : ”,

esc_attr( $product->get_type() ),

esc_html( ‘Rent Now’ ) // Custom button text

);

}

return $html;

}

add_filter( ‘woocommerce_loop_add_to_cart_link’, ‘my_custom_product_type_loop_add_to_cart_link’, 10, 2 );

“`

This is just one example, and could get much more complex if you have a custom booking system or other frontend interactions.

If you’re looking to enhance your WooCommerce store by creating a custom product type from scratch, you might find it helpful to explore a related article that delves into the intricacies of WooCommerce customization. This resource provides valuable insights and step-by-step guidance on various aspects of WooCommerce development, making it easier for you to implement your ideas effectively. For more detailed information, you can check out this informative article on WooCommerce customization.

Class Enhancements and Advanced Logic

Now that your basic custom product type is working, let’s explore how to add more sophisticated logic within your WC_Product_Rental class. This is where the real power of extending WC_Product comes into play.

Overriding Core WooCommerce Methods

Your WC_Product_Rental class can override any public or protected method from WC_Product or its parent WC_Data class. This includes methods for getting prices, managing stock, checking purchasability, and more.

Custom Price Logic

Let’s say your rental product has a different way of calculating its price. Maybe it’s a base price plus a daily rate.

“`php

// In class-wc-product-rental.php

class WC_Product_Rental extends WC_Product {

// … existing code …

/**

  • Returns the price of the product.
  • Overrides WC_Product::get_price()

*

  • @param string $context Context from which to get the price.
  • @return string price

*/

public function get_price( $context = ‘view’ ) {

$base_price = (float) parent::get_price( $context ); // Get the price set in backend

$daily_rate = (float) $this->get_meta( ‘_rental_daily_rate’, true ); // Custom meta field for daily rate

// Example: base price + daily rate (this is just an example, actual logic would be more complex)

// For a true rental system, price would depend on rental duration selected by user via frontend JS.

// For now, let’s just make it visually distinct.

$calculated_price = $base_price + $daily_rate; // This would be the “display price”

return apply_filters( ‘woocommerce_product_get_price’, $calculated_price, $this );

}

/**

  • Returns the regular price of the product.
  • Overrides WC_Product::get_regular_price()

*

  • @param string $context Context from which to get the price.
  • @return string price

*/

public function get_regular_price( $context = ‘view’ ) {

$base_price = (float) parent::get_regular_price( $context );

return apply_filters( ‘woocommerce_product_get_regular_price’, $base_price, $this );

}

/**

  • Returns the sale price of the product.
  • Overrides WC_Product::get_sale_price()

*

  • @param string $context Context from which to get the price.
  • @return string price

*/

public function get_sale_price( $context = ‘view’ ) {

$sale_price = (float) parent::get_sale_price( $context );

return apply_filters( ‘woocommerce_product_get_sale_price’, $sale_price, $this );

}

// You might also need to override get_price_html() to display custom price strings.

}

“`

Important Note on Price: Overriding get_price() is useful for displaying a custom price. However, for the actual price used in the cart and checkout, you’ll generally need to hook into woocommerce_before_calculate_totals and adjust the cart item price there based on your custom product data. Overriding get_price directly won’t change the cart’s calculations by itself.

Custom Purchasability

Perhaps your rental product needs specific conditions to be purchasable (e.g., only one can be rented at a time, or it’s unavailable on certain dates).

“`php

// In class-wc-product-rental.php

class WC_Product_Rental extends WC_Product {

// … existing code …

/**

  • Check if a product is purchasable.
  • Overrides WC_Product::is_purchasable()

*

  • @return bool

*/

public function is_purchasable() {

$purchasable = parent::is_purchasable(); // Start with default WooCommerce check

// Add your custom logic here

// Example: Only purchasable if not already rented for today (hypothetical)

if ( ! $this->is_available_for_rent_today() ) { // Custom method you’d define

$purchasable = false;

}

return apply_filters( ‘woocommerce_is_purchasable’, $purchasable, $this );

}

/**

  • Example custom method to check rental availability.
  • (You would implement actual availability logic here).

*

  • @return bool

*/

protected function is_available_for_rent_today() {

// Implement complex logic here:

// – Query custom tables for existing rentals

// – Check a custom ‘availability’ meta field

// – Integrate with a booking system

return true; // For demonstration, assume it’s always available

}

// You might also want to override get_availability() to change the stock message.

}

“`

Adding Custom Data Methods

It’s good practice to create helper methods in your product class to retrieve your custom metadata reliably, instead of calling get_post_meta() or get_meta() directly everywhere.

“`php

// In class-wc-product-rental.php

class WC_Product_Rental extends WC_Product {

// … existing code …

/**

  • Get the rental duration.
  • @param string $context
  • @return string

*/

public function get_rental_duration( $context = ‘view’ ) {

return $this->get_meta( ‘_rental_duration’, true, $context );

}

/**

  • Check if a deposit is required.
  • @param string $context
  • @return bool

*/

public function get_requires_deposit( $context = ‘view’ ) {

return ‘yes’ === $this->get_meta( ‘_rental_requires_deposit’, true, $context );

}

/**

  • Get the daily rental rate (assuming you added this to admin).
  • @param string $context
  • @return float

*/

public function get_rental_daily_rate( $context = ‘view’ ) {

return (float) $this->get_meta( ‘_rental_daily_rate’, true, $context );

}

}

“`

This makes your code cleaner and ensures consistency. When you’re on the frontend, instead of get_post_meta( $product->get_id(), '_rental_duration', true ), you’d simply use $product->get_rental_duration().

Cart and Checkout Integration

A custom product type often needs unique handling once it’s added to the cart. This could involve special pricing, custom validation, or different checkout processes.

Custom Price in Cart

As mentioned earlier, overriding get_price() in your product class primarily affects the displayed price. To modify the price in the cart, you’ll use the woocommerce_before_calculate_totals action.

“`php

function my_custom_product_type_adjust_cart_item_price( $cart_obj ) {

if ( is_admin() && ! defined( ‘DOING_AJAX’ ) ) {

return;

}

foreach ( $cart_obj->get_cart() as $key => $value ) {

$product = $value[‘data’];

if ( ‘rental’ === $product->get_type() ) {

// Let’s assume we have a custom meta _rental_rate_per_day

$rental_rate_per_day = (float) $product->get_meta( ‘_rental_rate_per_day’, true );

$rental_duration = $value[‘_rental_duration_in_cart’] ?? 1; // Get duration from cart item data

if ( $rental_rate_per_day > 0 && $rental_duration > 0 ) {

$custom_price = $rental_rate_per_day * $rental_duration;

$value[‘data’]->set_price( $custom_price );

}

}

}

}

add_action( ‘woocommerce_before_calculate_totals’, ‘my_custom_product_type_adjust_cart_item_price’, 10, 1 );

“`

This example assumes you have a way to get a _rental_duration_in_cart variable from the user selection (e.g., a custom field on the single product page that adds to cart item data).

Storing Custom Data with Cart Items

If your custom product requires user input (like rental dates, personalization, etc.) to be stored with the cart item, you’ll need to hook into the add-to-cart process.

“`php

// Add custom data from the custom fields to the cart item

function my_custom_product_type_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {

$product = wc_get_product( $product_id );

if ( ‘rental’ === $product->get_type() ) {

// Assume ‘_rental_duration_input’ is the name of a hidden/visible field on single product page

if ( isset( $_POST[‘_rental_duration_input’] ) && ! empty( $_POST[‘_rental_duration_input’] ) ) {

$cart_item_data[‘_rental_duration_in_cart’] = sanitize_text_field( $_POST[‘_rental_duration_input’] );

}

// Always return the cart item data.

}

return $cart_item_data;

}

add_filter( ‘woocommerce_add_cart_item_data’, ‘my_custom_product_type_add_cart_item_data’, 10, 3 );

“`

To then display this data in the cart/checkout:

“`php

// Display custom cart item data on cart/checkout pages

function my_custom_product_type_display_cart_item_data( $item_data, $cart_item ) {

if ( isset( $cart_item[‘_rental_duration_in_cart’] ) ) {

$item_data[] = array(

‘key’ => __( ‘Rental Duration’, ‘my-custom-product-type’ ),

‘display’ => $cart_item[‘_rental_duration_in_cart’],

);

}

return $item_data;

}

add_filter( ‘woocommerce_get_item_data’, ‘my_custom_product_type_display_cart_item_data’, 10, 2 );

// And store it as order item meta when order is created

function my_custom_product_type_add_order_item_meta( $item_id, $values, $cart_item_key ) {

if ( isset( $values[‘_rental_duration_in_cart’] ) ) {

wc_add_order_item_meta( $item_id, ‘_rental_duration_ordered’, $values[‘_rental_duration_in_cart’] );

}

}

add_action( ‘woocommerce_add_order_item_meta’, ‘my_custom_product_type_add_order_item_meta’, 10, 3 );

“`

This ensures that any user-specific data associated with your custom product type is carried through the entire checkout process and stored with the order.

There you have it – a foundational guide to building your own custom product type in WooCommerce. It’s a journey into the core of WooCommerce, but with PHP, careful hooking, and a structured approach, you can tailor it precisely to your unique needs.