Create a small amount of code to capture marketing sign-up consent in your WooCommerce checkout. Then register your new customer in your Sendinblue contact list.
We’ll inject a tick box into the WooCommerce checkout fields, then capture the user’s choice (sign-up or don’t sign-up) when the order is created. Finally, if the customer wants to sign-up, we’ll send a request to the Sendinblue servers via their API.
It sounds like a bit of a chunk, but there’s not much to it when you break it down into small pieces.
In our example, the Sendinblue contacts list has a ListId of 3 (yours will probably be different) and we’re passing attributes called FIRSTNAME and LASTNAME. If you’re using something like FNAME or LNAME, you’ll need to adjust things slightly.
importantMake sure you’re using a custom child theme so you can edit functions.php.
Scaffold the Code
To get started, go into your custom child theme’s folder, create a new file called wpt-checkout-sendinblue.php and paste the following into it:
<?php /** * WP Tutorials Checkout Send in Blue (WPTCSIB) * * https://wp-tutorials.tech/refine-wordpress/signup-to-sendinblue-from-the-checkout/ * */ // Block direct access. defined('WPINC') || die(); const WPTCSIB_SIGNUP_FIELD_NAME = 'customer_signup_for_marketing'; const WPTCSIB_SENDINBLUE_API_KEY = 'xxxxxxxxxxxx'; // Enter your Sendinblue v3 API key in here const WPTCSIB_LIST_ID = 3; // Get the List Id from your sendinblue account.
Then edit your theme’s functions.php file and add the following:
// WooCommerce checkout send-in-blue require_once dirname(__FILE__) . '/wpt-checkout-sendinblue.php';
Save all that and then load some content on your site – everything should still be working. That’s the placeholder/scaffold code sorted out.
Add the Sign-up Checkbox
Next up, open wpt-checkout-sendinblue.php again and paste the following code into it.
/** * Inject a panel with a checkbox in it into our checkout form, * so customers can sign up to special offer emails. */ function add_marketing_signup_to_billing_form() { echo '<div class="marketing-fields">'; printf( '<p class="form-row"><label><input name="%s" type="checkbox" /><span>%s</span></label></p>', WPTCSIB_SIGNUP_FIELD_NAME, esc_html__('Let me know when there are special offers and discounts') ); printf( '<p class="form-row">%s</p>', esc_html__('We will not sell or give your details to anyone else, and you can opt-out if you want.') ); echo '</div>'; // .marketing-fields } add_action('woocommerce_after_checkout_billing_form', 'add_marketing_signup_to_billing_form');
All we’re doing here is hooking a checkout page action, and then outputting some HTML. There are several actions that can work for this:
- woocommerce_before_checkout_billing_form
- woocommerce_after_checkout_billing_form
- woocommerce_before_order_notes
- woocommerce_after_order_notes
- woocommerce_checkout_after_customer_details
The HTML is pretty straightforward too – we just open a container <div>
, then print two paragraphs. The first one has our checkbox within a label, and the second has some text to explain what we’re doing with the customer’s consent. Then we just close the container <div>
.
Notice how we’ve used a constant called WPTCSIB_SIGNUP_FIELD_NAME
to hold the name of our checkbox field.
Try adding a product to your cart and going to the checkout – you should see the new checkbox in there.
/** * Marketing fields on the checkout page. */ .woocommerce-checkout .marketing-fields { margin: 1em 0; border: 1px solid #dddddd; background-color: #f0f0f0; padding: 1em; border-radius: 0.5em; } .woocommerce-checkout .marketing-fields input[type="checkbox"] { margin-right: 0.5em; }
Some CSS for your “style.css”, to get things started.
Detect the Checkbox When the Order is Created
After WooCommerce creates a new order, it triggers the woocommerce_checkout_update_order_meta action. We can hook this and check if the $_POST array contains our checkbox field.
Edit wpt-checkout-sendinblue.php and add the following snippet at the end of the file:
/** * When a new order has been created, see if the customer has signed up * for notifications. */ function check_for_marketing_signup($order_id, $data) { if (!array_key_exists(WPTCSIB_SIGNUP_FIELD_NAME, $_POST)) { error_log(__FUNCTION__ . ' : The checkbox field has not been POSTed'); } elseif (!filter_var($_POST[WPTCSIB_SIGNUP_FIELD_NAME], FILTER_VALIDATE_BOOLEAN)) { error_log(__FUNCTION__ . ' : The value in our checkbox field does not resolve to true'); } elseif (empty($order = wc_get_order($order_id))) { error_log(__FUNCTION__ . ' : Failed to get the newly created WC_Order object. Weird'); } else { add_contact_to_sendinblue( $order->get_billing_email(), $order->get_billing_first_name(), $order->get_billing_last_name() ); } } add_action('woocommerce_checkout_update_order_meta', 'check_for_marketing_signup', 10, 2);
Usually when processing form data, we’d want to have a nonce in the POST data and use wp_verify_nonce() to check it’s come from a valid source. In this case, WooCommerce has done all that for us… so all we need to do is grab a copy of the WC_Order object and pick up the relevant billing fields.
Create the Contact in Sendinblue
Now we’ve captured the customer’s consent to sign-up, we need to make a call to the Sendinblue API. We’ve wrapped this in a tidy little function so we can call it from elsewhere, if we want to. Add the following into wpt-checkout-sendinblue.php:
/** * Add a contact to your Send-in-blue contact list by calling their API. */ function add_contact_to_sendinblue(string $email_address, string $first_name, string $last_name) { if (!function_exists('curl_init')) { error_log(__FUNCTION__ . ' : Is the PHP Curl extension isntalled?'); } elseif (strpos(WPTCSIB_SENDINBLUE_API_KEY, 'xkeysib-') !== 0) { error_log(__FUNCTION__ . ' : Invalid Sendinblue API key'); } else if (empty($sanitised_email_address = sanitize_email($email_address))) { error_log(__FUNCTION__ . ' : The billing email address is not present or is not valid'); } elseif (empty($first_name = sanitize_text_field($first_name))) { error_log(__FUNCTION__ . ' : The order does not have a billing first name'); } elseif (empty($last_name = sanitize_text_field($last_name))) { error_log(__FUNCTION__ . ' : The order does not have a billing last name'); } else { // Check that the attributes here are available in your // Sendinblue contact list. $request = array( 'email' => $sanitised_email_address, 'attributes' => array( 'FIRSTNAME' => $first_name, 'LASTNAME' => $last_name, ), 'emailBlacklisted' => false, 'smsBlacklisted' => false, 'listIds' => array(WPTCSIB_LIST_ID), 'updateEnabled' => true, ); // The options for our API call. $curl_options = array( CURLOPT_URL => 'https://api.sendinblue.com/v3/contacts', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 10, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode($request), CURLOPT_HTTPHEADER => array( 'accept: application/json', 'api-key: ' . WPTCSIB_SENDINBLUE_API_KEY, 'content-type: application/json', ), ); // Create a Curl instance. $ch = curl_init(); // Configure the Curl instance. curl_setopt_array($ch, $curl_options); // Diagnostics. // error_log(__FUNCTION__ . ' : Calling the Send-in-Blue API for ' . $sanitised_email_address); // Make the actual API call. // $json_response holds the returned JSON, in case you want to do // something with it. $json_response = curl_exec($ch); // HTTP response code from the Sendinblue server: // 201 means the contact was created. // 204 means an existing contact was updated. $response_code = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE)); // Release the Curl instance. curl_close($ch); } }
This is a tidy reusable function. Like all tidy functions, it follows a standard pattern:
- Check the environment is OK (make sure that Curl is installed).
- Validate the inputs (make sure that the contact’s details are not garbage).
- Do the actual work (Call the Sendinblue API).
- Optionally return a result (We don’t return anything here).
Wrapping Up
That’s all there is to it. We render some HTML in a form, capture the data via $_POST
, validate the data, then POST it to the Sendinblue API using PHP’s Curl functions.
More information on how to use a REST API from WordPress.
Happy marketing 😎 👍
Great tutorial!
How do i add additional fields such as OPT_IN or DOUBLE_OPT_IN ?
Double Opt-in is a bit more difficult, because you need a redirect URL and a template set up in Sendinblue. You should be able to use our example and change the POST endpoint from “https://api.sendinblue.com/v3/contacts” to “https://api.sendinblue.com/v3/contacts/doubleOptinConfirmation” and add the extra fields to the POST array. Have a look at the Sendinblue reference, here: https://developers.sendinblue.com/reference/createdoicontact. On the right-hand-side of the docs there’s a panel that lets you test Curl POSTs. You can see the POST array you need to create in there.
Example:
Thanks for the tutorial!
I’m having trouble figuring out why the contact info is not showing up in SendinBlue. I got the checkbox to show up on the checkout page, but after purchasing an item, the person’s contact info is not showing up in SendinBlue.
I made sure the API is correct, But what else can I check to see why it’s not working?
Thanks
Hi!
I’ve just modified the code in the tutorial to output some useful messages in the site’s error log. Try the new code and see what happens at your end – you should get a meaningful messages now.
If you don’t have easy access to your site’s error logs, the “Query Monitor” plugin will help you out.
Let me know how you get on.
Sorry, I’m not exactly sure how to use Query Monitor plugin. I installed it, but it looks like I need to set it up to show the logs. It says, ‘no data logged.’
I’m using GeneratePress theme and created my own plugin for using custom PHP code. I didn’t want to insert this code, require_once dirname(__FILE__) . ‘/wpt-checkout-sendinblue.php’, into my function.php because it would get overwritten once the theme updates. But when I insert it into my custom plugin, I get a fetal error. Although having this code in function.php works fine. Can I change this code to use it in my custom plugin?
Is there anything else I need to change for this work besides adding API_Key and List_ID?
Thanks for your help!
Hi Viktor
That’s odd about the code working in the custom plugin but not as part of the theme. I originally wrote the code for a client, and it’s part of a custom plugin on their site too. I’ll check over the tutorial code – it’s over a year old now so it could do with refreshing. I’ll email you directly when I’ve had a look at it.
Thanks, actually, the code works in function.php but not in a custom plugin.
Thank you for this tutorial. Seems very helpful. But I’m working on Oxygen builder; there is no theme nor child theme. So, where can I place the file “wpt-checkout-sendinblue.php”
Thanks in advance.
Oh dear. That’s annoying. You will have to create a small plugin instead of using a child theme. It’s quite easy though.
To create a small custom plugin, make a folder in wp-content/plugins called “wpt-checkout-sendinblue”. In this folder, create a file called “wpt-checkout-sendinblue.php” and use this as the header:
/**
* Plugin Name: WPT Checkout Sendinblue
* Plugin URI: https://wp-tutorials.tech/refine-wordpress/signup-to-sendinblue-from-the-checkout/
* Description: Put a description in here...
* Version: 1.0.0
* Author: Headwall WP Tutorials
* Author URI: https://wp-tutorials.tech/
* License: GPLv3 or later
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
* Text Domain: wpt-checkout-sendinblue
* Domain Path: /languages
*/
// Put the rest of the tutorial PHP code in here
// ...
// ...
Then you should be able to put all the PHP code in here and activate your custom plugin. I hope this helps.