Fonctionnement de la relance des “paniers abandonnés” via Sendinblue

Le principe est simple, on va dans la partie «automation» de Sendinblue, on crée un nouveau scénario et on choisit «Panier abandonné». Simple, mais trop beau pour être vrai ! Tout se complique maintenant, Sendinblue vous demande les déclencheurs de votre scénario, or, ces déclencheurs vous ne les avez pas encore mis en place sur votre site. D’ailleurs, à cet instant, il est probable que vous ne sachiez pas du tout de quoi je parle. Pas de panique, enfin pas encore !

Revenons en à nos moutons : pour commencer, Il vous faut des événements déclencheurs afin de pouvoir entrer dans le scénario. Par exemple, un internaute ajoute un produit dans son panier et c’est là que votre système d’envoi automatique de paniers abandonnés se met en route. Néanmoins pour avoir un email avec un contenu suffisamment pertinent pour ce type de relance, et qui soit réellement utile pour vos internautes, nous devons trouver un moyen d’y insérer leur panier tel qu’il était rempli sur le site internet. D’ailleurs, nous n’oublierons pas le lien, afin que l’internaute puisse y accéder facilement. Normalement, à ce moment, vous comprenez que nous avons besoin que toutes ces informations soient dans Sendinblue.

Dans ce billet nous allons regarder comment faire cela avec les codes JavaScript proposés par Sendinblue, une dose de courage et un soupçon de patience.

La technique c’est maintenant

Installation du module Sendinblue pour prestashop (v1.6)

Pour installer le module Sendinblue sur votre boutique, je ne vais rien ré-inventer. La documentation de Sendinblue est très bien faite, je vous invite à suivre la procédure. Une petite subtilité à noter : la clé d’API attendue qui se trouve dans votre compte Sendinblue sera la clé V2.

Identification des actions à remonter

Le module prestashop étant configuré et le marketing automation activé. Nous allons pouvoir passer à la partie code.
Voici les actions de nos internautes qui nous intéressent et que nous allons utiliser :

  • L’ajout de produits dans le panier (add_basket)
  • La création d’un panier (cart_created)
  • La confirmation de commande (order_confirmation)

À l’usage, il y a un problème important avec les étapes identifiées ci-dessus. En effet, il faut que l’internaute soit identifié par Sendinblue (email connu) pour pouvoir lier ses actions sur le site et le scénario que l’on mettra en place par la suite dans Sendinblue. Si une action remonte sans que l’internaute ne soit reconnu grâce à son adresse email, l’action ne sera pas utilisable.

Le module Prestashop réalisé par Sendinblue est plutôt bien fait et va nous aider pour l'identification. Toutefois, lors de leur première visite, de nombreux internautes ajouterons des produits directement dans leur panier avant même de créer un compte. C’est à vrai dire le cas de tous vos nouveaux clients. Pour répondre à ce modèle de parcours client, nous devons ajouter une étape supplémentaire afin de déclencher une action d’identification spécifiquement pour Sendinblue, à savoir :

  • La connexion à un compte dans le tunnel de conversion du panier (order_logged) Cette étape survient juste avant le choix des adresses de facturation et de livraison.

Quand Javascript, .php et .tpl s’entremêlent !

Allez c’est le moment de sortir le développeur du placard.

blockcart/ajax-cart.js

Il faut créer un override du fichier /modules/blockcart/ajax-cart.js</p>

dans votre thème /themes/[votre-theme]/js/blockcart/ajax-cart.js

Rechercher la méthode Ajax d’ajout d’un produit au panier qui doit se trouver aux alentours de la ligne 207 avec le terme de recherche suivant : controller=cart&add=1&ajax=true

vous devriez trouver sans trop de problème dans la méthode success de l’appel Ajax c’est à dire après l’accolade il faut ajouter le code suivant :

	
		//Script de stockage des informations du panier
		sendinblue.track(
			'cart_created',
			{
			 "FIRSTNAME": "John",
			 "LASTNAME" : "Doe",
			},
			{
			 "id": jsonData.cart_id,
			 "data": jsonData
			}
		 );
		// Script pour l'ajout au panier                
		window.sendinblue.track( 'add_basket',
		{
			'id_product':idProduct,
			'quantity':quantity
		}
		);
	

Vous devriez avoir quelque chose ressemblant à cela :

	
		success: function(jsonData,textStatus,jqXHR)
		{
			//Script de stockage des informations du panier
			sendinblue.track(
				'cart_created',
				{
				 "FIRSTNAME": "John",
				 "LASTNAME" : "Doe",
				},
				{
				 "id": jsonData.cart_id,
				 "data": jsonData
				}
			 );
			// Script pour l'ajout au panier                
			window.sendinblue.track( 'add_basket',
			{
				'id_product':idProduct,
				'quantity':quantity
			}
			);
	

Inutile de vous attarder sur les attributs nom et prénom nous ne nous en servirons pas. Cet appel javascript sera l’un de nos déclencheurs du scénario «Panier abandonné».

OrderController.php

faire l’override dans le dossier override/controller/front/

Dupliquer la méthode public function initContent()

Rechercher case OrderController::STEP_PAYMENT:

Ajouter dans ce bloc avant $this->_assignSummaryInformations(); le code suivant

	
		$this->context->smarty->assign(array(
		   'total_paid_tax_incl' => number_format($this->context->cart->getOrderTotal(true), 2, '.', ' '),
		   'id_order' => $this->context->cart->id,                   
		));
	

OrderConfirmationController.php

faire l’override dans le dossier override/controller/front/

Dupliquer la méthode public function initContent()

Modifier le number_format de la variable total_paid_tax_incl pour qu’on puisse l’envoyer à sendinblue et l’utiliser dans le template email. (attention vous aurez probablement un effet de bord sur l’affichage du site)

	
		'total_paid_tax_incl' => number_format($order->total_paid_tax_incl, 2, '.', ' '),
	

Les informations suivantes pourront ensuite être remontées à Sendinblue dans les étapes de validation d’adresse, de paiement et de confirmation de commande.

order-address.tpl

Chemin - /themes/[votre-theme]/order-address.tpl

Ajoutez ce code avant les appels Js et Css logiquement avant la balise smarty

	
	 {strip}
		
	

order-payment.tpl

Chemin - /themes/[votre-theme]/order-payment.tpl

Ajouter ce code en fin de fichier

	
		
	

blockcart.php

faire l’override dans le dossier override/modules/blockcart/

la méthode qu’il faut override est «assignContentVars« ce que l’on veut absolument c’est l’ajout du hash pour préparer l'auto connexion pour le ré-affichage du panier.

	
	public function assignContentVars($params)
		{
			global $errors;

			// Set currency
			if ((int)$params['cart']->id_currency && (int)$params['cart']->id_currency != $this->context->currency->id)
				$currency = new Currency((int)$params['cart']->id_currency);
			else
				$currency = $this->context->currency;

			$taxCalculationMethod = Group::getPriceDisplayMethod((int)Group::getCurrent()->id);

			$useTax = !($taxCalculationMethod == PS_TAX_EXC);

			$products = $params['cart']->getProducts(true);
			$nbTotalProducts = 0;
			foreach ($products as $product)
				$nbTotalProducts += (int)$product['cart_quantity'];
			$cart_rules = $params['cart']->getCartRules();

			if (empty($cart_rules))
				$base_shipping = $params['cart']->getOrderTotal($useTax, Cart::ONLY_SHIPPING);
			else
			{
				$base_shipping_with_tax    = $params['cart']->getOrderTotal(true, Cart::ONLY_SHIPPING);
				$base_shipping_without_tax = $params['cart']->getOrderTotal(false, Cart::ONLY_SHIPPING);
				if ($useTax)
					$base_shipping = $base_shipping_with_tax;
				else
					$base_shipping = $base_shipping_without_tax;
			}
			$shipping_cost = Tools::displayPrice($base_shipping, $currency);
			$shipping_cost_float = Tools::convertPrice($base_shipping, $currency);
			$wrappingCost = (float)($params['cart']->getOrderTotal($useTax, Cart::ONLY_WRAPPING));
			$totalToPay = $params['cart']->getOrderTotal($useTax);

			if ($useTax && Configuration::get('PS_TAX_DISPLAY') == 1)
			{
				$totalToPayWithoutTaxes = $params['cart']->getOrderTotal(false);
				$this->smarty->assign('tax_cost', Tools::displayPrice($totalToPay - $totalToPayWithoutTaxes, $currency));
			}

			// The cart content is altered for display
			foreach ($cart_rules as &$cart_rule)
			{
				if ($cart_rule['free_shipping'])
				{
					$shipping_cost = Tools::displayPrice(0, $currency);
					$shipping_cost_float = 0;
					$cart_rule['value_real'] -= Tools::convertPrice($base_shipping_with_tax, $currency);
					$cart_rule['value_tax_exc'] = Tools::convertPrice($base_shipping_without_tax, $currency);
				}
				if ($cart_rule['gift_product'])
				{
					foreach ($products as $key => &$product)
					{
						if ($product['id_product'] == $cart_rule['gift_product']
							&& $product['id_product_attribute'] == $cart_rule['gift_product_attribute'])
						{
							$product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'],
								(int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
							$product['total'] = Tools::ps_round($product['total'] - $product['price'],
								(int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
							if ($product['cart_quantity'] > 1)
							{
								array_splice($products, $key, 0, array($product));
								$products[$key]['cart_quantity'] = $product['cart_quantity'] - 1;
								$product['cart_quantity'] = 1;
							}
							$product['is_gift'] = 1;
							$cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'],
								(int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
							$cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'],
								(int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_);
						}
					}
				}
			}

			$total_free_shipping = 0;
			if ($free_shipping = Tools::convertPrice(floatval(Configuration::get('PS_SHIPPING_FREE_PRICE')), $currency))
			{
				$total_free_shipping =  floatval($free_shipping - ($params['cart']->getOrderTotal(true, Cart::ONLY_PRODUCTS) +
					$params['cart']->getOrderTotal(true, Cart::ONLY_DISCOUNTS)));
				$discounts = $params['cart']->getCartRules(CartRule::FILTER_ACTION_SHIPPING);
				if ($total_free_shipping < 0)
					$total_free_shipping = 0;
				if (is_array($discounts) && count($discounts))
					$total_free_shipping = 0;
			}

			$this->smarty->assign(array(
				'products' => $products,
				'cart_id' => (int)$params['cart']->id,
				'hash' => md5(_COOKIE_KEY_.'recover_cart_'.(int)$params['cart']->id),
				'customizedDatas' => Product::getAllCustomizedDatas((int)($params['cart']->id)),
				'CUSTOMIZE_FILE' => Product::CUSTOMIZE_FILE,
				'CUSTOMIZE_TEXTFIELD' => Product::CUSTOMIZE_TEXTFIELD,
				'discounts' => $cart_rules,
				'nb_total_products' => (int)($nbTotalProducts),
				'shipping_cost' => $shipping_cost,
				'shipping_cost_float' => $shipping_cost_float,
				'show_wrapping' => $wrappingCost > 0 ? true : false,
				'show_tax' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')),
				'wrapping_cost' => Tools::displayPrice($wrappingCost, $currency),
				'product_total' => Tools::displayPrice($params['cart']->getOrderTotal($useTax, Cart::BOTH_WITHOUT_SHIPPING), $currency),
				'total' => Tools::displayPrice($totalToPay, $currency),
				'order_process' => Configuration::get('PS_ORDER_PROCESS_TYPE') ? 'order-opc' : 'order',
				'ajax_allowed' => (int)(Configuration::get('PS_BLOCK_CART_AJAX')) == 1 ? true : false,
				'static_token' => Tools::getToken(false),
				'free_shipping' => $total_free_shipping
			));
			if (count($errors))
				$this->smarty->assign('errors', $errors);
			if (isset($this->context->cookie->ajax_blockcart_display))
				$this->smarty->assign('colapseExpandStatus', $this->context->cookie->ajax_blockcart_display);
		}
	

En théorie et si je n’ai pas oublié de vous faire ajouter un override, on a ce qu’il nous faut pour passer à la partie Sendinblue.

Mise en place du scénario Sendinblue

Nous allons réaliser le scénario ci-après ensemble. Nous avons notre objectif mais avant le côté sexy du scénario nous devons préparer l’email.

Visuel du scénario qui va être réaliser

Création du template email

Aller dans l’onglet «Automation» de Sendinblue et cliquer sur «Templates d’emails»

Puis ajouter un nouveau template et préparer sa configuration pour pouvoir passer à l’onglet conception.

Pour le moment je n’ai pas trouvé de solution pour utiliser le système de template en glisser déposer de Sendinblue. les boucles (for each) qui permettent de boucler sur les données remontées par Prestashop dans Sendinblue ne sont pas applicables à un bloc complet et reste difficile à utiliser. Il est impossible de fabriquer un récapitulatif du panier de l’internaute éditable par tout un chacun pour l’instant. Pour le coup, nous allons créer un template email à partir d’un fichier html déjà fait que vous adapterez ensuite à votre goût.

Pour cela, utilisons un template responsive créé par un guru de l’email Ted Goas un simple CTRL + S sur cette page vous permettra de le récupérer (Github du projet Cerberus email).

Ouvrez-le avec un éditeur de texte classique et recherchez en fin de fichier les lignes suivantes

Juste avant insérez le code suivant

Puis importer le tout dans votre template Sendinblue

Vous devriez obtenir quelque chose qui ressemble à la capture suivante.

capture d'ecran de l'email en cours de réalisation

Vu comme cela ce n’est pas dingue mais ca fait le job !

J’ai mis en place une boucle de Sendinblue sur les paramètres qui arriveront de Prestashop.

Pour chaque ligne de produit dans le panier, on ajoutera une ligne de plus dans l’email

Et on aura un joli total à la fin.

Enfin, il manque un CTA (Call To Action) pour renvoyer l’internaute vers son panier comme nous l’avions évoqué dans le paragraphe : «Principe de fonctionnement».

Il faut ajouter encore un peu de code à la suite de ce que vous avez déjà ajouté :

Vous devez remplacer [Votre site web] par le domaine de votre site e-commerce prestashop.

Si vous avez bien travaillé, vous obtenez ceci :

capture d'ecran de l'email en cours de réalisation avec CTA

Pour en finir avec cette étape : on enregistre et on active le template.

Création du scénario

Allez dans l’onglet Automation, créez un nouveau scénario et choisissez scénario personnalisé.

Ajouter un point d’entrée > «Activité liée à votre site» > «Événement personnalisé»

Choisissez «Événements personnalisés (Track Event)» et ajoutez dans le champs «add_basket»

Puis faites «OK»

Ajoutez un autre point d’entrée > «Activité liée à votre site» > «Événement personnalisé»

Choisissez «Événement personnalisé (Track Event)» et ajoutez dans le champs «order_logged»

Puis faites «OK»

Ensuite cliquez sur le «+» en dessous des deux points d’entrée que vous avez créés

dans la partie «Condition», choisissez «Attendre jusqu’à» > «Activité du site web»

Sélectionnez l’option «Jusqu’à ce qu’un Track Event ait lieu» et ajoutez dans le champ «order_confirmation».

Sélectionnez la durée d’attente de votre panier abandonné (perso j’ai choisi une longue attente d’une journée)

Puis cliquez sur «OK»

Vous devriez avoir deux éléments qui s’affichent : «Oui» et «Non»

cliquez sur le «+» sous le «Non» pour Ajouter «Envoyer un email» puis sélectionnez votre template.

Vous pouvez vous envoyer une copie si vous le souhaitez pour tester ce que vos internautes reçoivent et ajouter une planification pour que les emails partent selon une tranche horaire spécifique.

Cochez la case «Utiliser les données des événements» pour personnaliser l’email,

sélectionnez l’option «Les données du dernier événement reçu»

et Ajoutez dans le champ «cart_created».

Puis faites «OK»

Et voilà !

Bon, il faut quand même que je vous explique ce que l’on vient de faire ensemble.

Vous venez de créer deux déclencheurs pour votre scénario. C’est à dire que vous dites à Sendinblue de faire entrer les internautes qui ont fait exécuter vos codes javascripts «add_basket» et/ou «order_logged» ensuite votre scénario met les internautes en attente pendant le temps que vous avez choisi (dans mon cas j’ai choisi une journée) si au bout de ce temps d’attente, l’internaute n’a pas envoyé d’action «order_confirmation» l’email de relance de panier abandonné sera envoyé avec les données du dernier envoi javascript «cart_created». L’email sera rempli avec les dernières informations du panier de l’internaute.

Quelques conseils :

  • Pour vos tests, vous pouvez ajouter une restriction sur uniquement votre email avant l’envoi des emails. Ainsi vous pourrez le tester sur vous avant de vous lancer dans le grand bain. Rien ne vous empêche du coup de mettre le délai d’attente à quelques secondes.
  • Pendant la phase de tests sur vos prospects et clients, je vous conseille d’être en copie des emails afin de vous assurer que ce qu’ils reçoivent correspond à ce que vous aviez prévu.
  • Ajoutez à votre template un tag du style «panier_abandon» pour pouvoir suivre facilement vos statistiques transactionnelles. Les envois de la partie automation apparaissent dans les logs de la partie transactionnelle de Sendinblue.
  • Pensez également à remplir un «utm_campaign» suffisamment intelligible pour vos mesures analytics
  • N’hésitez pas à vous munir d’un développeur et d’une bonne dose de courage avant de vous lancer dans l’aventure.

Et si jamais la peur vous bloque, vous pouvez toujours faire appel à nous pour votre projet.

Principe de fonctionnement

Le principe est simple, on va dans la partie «automation» de Sendinblue, on crée un nouveau scénario et on choisit «Panier abandonné». Simple, mais trop beau pour être vrai ! Tout se complique maintenant, Sendinblue vous demande les déclencheurs de votre scénario, or, ces déclencheurs vous ne les avez pas encore mis en place sur votre site. D’ailleurs, à cet instant, il est probable que vous ne sachiez pas du tout de quoi je parle. Pas de panique, enfin pas encore !

Revenons en à nos moutons : pour commencer, Il vous faut des événements déclencheurs afin de pouvoir entrer dans le scénario. Par exemple, un internaute ajoute un produit dans son panier et c’est là que votre système d’envoi automatique de paniers abandonnés se met en route. Néanmoins pour avoir un email avec un contenu suffisamment pertinent pour ce type de relance, et qui soit réellement utile pour vos internautes, nous devons trouver un moyen d’y insérer leur panier tel qu’il était rempli sur le site internet. D’ailleurs, nous n’oublierons pas le lien, afin que l’internaute puisse y accéder facilement. Normalement, à ce moment, vous comprenez que nous avons besoin que toutes ces informations soient dans Sendinblue.

Dans ce billet nous allons regarder comment faire cela avec les codes JavaScript proposés par Sendinblue, une dose de courage et un soupçon de patience.

La technique c’est maintenant

Installation du module Sendinblue pour prestashop (v1.6)

Pour installer le module Sendinblue sur votre boutique, je ne vais rien ré-inventer. La documentation de Sendinblue est très bien faite, je vous invite à suivre la procédure. Une petite subtilité à noter : la clé d’API attendue qui se trouve dans votre compte Sendinblue sera la clé V2.

Identification des actions à remonter

Le module prestashop étant configuré et le marketing automation activé. Nous allons pouvoir passer à la partie code.
Voici les actions de nos internautes qui nous intéressent et que nous allons utiliser :

  • L’ajout de produits dans le panier (add_basket)
  • La création d’un panier (cart_created)
  • La confirmation de commande (order_confirmation)

À l’usage, il y a un problème important avec les étapes identifiées ci-dessus. En effet, il faut que l’internaute soit identifié par Sendinblue (email connu) pour pouvoir lier ses actions sur le site et le scénario que l’on mettra en place par la suite dans Sendinblue. Si une action remonte sans que l’internaute ne soit reconnu grâce à son adresse email, l’action ne sera pas utilisable.

Le module Prestashop réalisé par Sendinblue est plutôt bien fait et va nous aider pour l'identification. Toutefois, lors de leur première visite, de nombreux internautes ajouterons des produits directement dans leur panier avant même de créer un compte. C’est à vrai dire le cas de tous vos nouveaux clients. Pour répondre à ce modèle de parcours client, nous devons ajouter une étape supplémentaire afin de déclencher une action d’identification spécifiquement pour Sendinblue, à savoir :

  • La connexion à un compte dans le tunnel de conversion du panier (order_logged) Cette étape survient juste avant le choix des adresses de facturation et de livraison.

Quand Javascript, .php et .tpl s’entremêlent !

Allez c’est le moment de sortir le développeur du placard.

blockcart/ajax-cart.js

Il faut créer un override du fichier /modules/blockcart/ajax-cart.js</p>

dans votre thème /themes/[votre-theme]/js/blockcart/ajax-cart.js

Rechercher la méthode Ajax d’ajout d’un produit au panier qui doit se trouver aux alentours de la ligne 207 avec le terme de recherche suivant : controller=cart&add=1&ajax=true

vous devriez trouver sans trop de problème dans la méthode success de l’appel Ajax c’est à dire après l’accolade il faut ajouter le code suivant :

  //Script de stockage des informations du panier sendinblue.track( 'cart_created', { "FIRSTNAME": "John", "LASTNAME" : "Doe", }, { "id": jsonData.cart_id, "data": jsonData } ); // Script pour l'ajout au panier window.sendinblue.track( 'add_basket', { 'id_product':idProduct, 'quantity':quantity } );  

Vous devriez avoir quelque chose ressemblant à cela :

  success: function(jsonData,textStatus,jqXHR) { //Script de stockage des informations du panier sendinblue.track( 'cart_created', { "FIRSTNAME": "John", "LASTNAME" : "Doe", }, { "id": jsonData.cart_id, "data": jsonData } ); // Script pour l'ajout au panier window.sendinblue.track( 'add_basket', { 'id_product':idProduct, 'quantity':quantity } );  

Inutile de vous attarder sur les attributs nom et prénom nous ne nous en servirons pas. Cet appel javascript sera l’un de nos déclencheurs du scénario «Panier abandonné».

OrderController.php

faire l’override dans le dossier override/controller/front/

Dupliquer la méthode public function initContent()

Rechercher case OrderController::STEP_PAYMENT:

Ajouter dans ce bloc avant $this->_assignSummaryInformations(); le code suivant

  $this->context->smarty->assign(array( 'total_paid_tax_incl' => number_format($this->context->cart->getOrderTotal(true), 2, '.', ' '), 'id_order' => $this->context->cart->id, ));  

OrderConfirmationController.php

faire l’override dans le dossier override/controller/front/

Dupliquer la méthode public function initContent()

Modifier le number_format de la variable total_paid_tax_incl pour qu’on puisse l’envoyer à sendinblue et l’utiliser dans le template email. (attention vous aurez probablement un effet de bord sur l’affichage du site)

  'total_paid_tax_incl' => number_format($order->total_paid_tax_incl, 2, '.', ' '),  

Les informations suivantes pourront ensuite être remontées à Sendinblue dans les étapes de validation d’adresse, de paiement et de confirmation de commande.

order-address.tpl

Chemin - /themes/[votre-theme]/order-address.tpl

Ajoutez ce code avant les appels Js et Css logiquement avant la balise smarty

  {strip}   

order-payment.tpl

Chemin - /themes/[votre-theme]/order-payment.tpl

Ajouter ce code en fin de fichier

    

blockcart.php

faire l’override dans le dossier override/modules/blockcart/

la méthode qu’il faut override est «assignContentVars« ce que l’on veut absolument c’est l’ajout du hash pour préparer l'auto connexion pour le ré-affichage du panier.

  public function assignContentVars($params) { global $errors; // Set currency if ((int)$params['cart']->id_currency && (int)$params['cart']->id_currency != $this->context->currency->id) $currency = new Currency((int)$params['cart']->id_currency); else $currency = $this->context->currency; $taxCalculationMethod = Group::getPriceDisplayMethod((int)Group::getCurrent()->id); $useTax = !($taxCalculationMethod == PS_TAX_EXC); $products = $params['cart']->getProducts(true); $nbTotalProducts = 0; foreach ($products as $product) $nbTotalProducts += (int)$product['cart_quantity']; $cart_rules = $params['cart']->getCartRules(); if (empty($cart_rules)) $base_shipping = $params['cart']->getOrderTotal($useTax, Cart::ONLY_SHIPPING); else { $base_shipping_with_tax = $params['cart']->getOrderTotal(true, Cart::ONLY_SHIPPING); $base_shipping_without_tax = $params['cart']->getOrderTotal(false, Cart::ONLY_SHIPPING); if ($useTax) $base_shipping = $base_shipping_with_tax; else $base_shipping = $base_shipping_without_tax; } $shipping_cost = Tools::displayPrice($base_shipping, $currency); $shipping_cost_float = Tools::convertPrice($base_shipping, $currency); $wrappingCost = (float)($params['cart']->getOrderTotal($useTax, Cart::ONLY_WRAPPING)); $totalToPay = $params['cart']->getOrderTotal($useTax); if ($useTax && Configuration::get('PS_TAX_DISPLAY') == 1) { $totalToPayWithoutTaxes = $params['cart']->getOrderTotal(false); $this->smarty->assign('tax_cost', Tools::displayPrice($totalToPay - $totalToPayWithoutTaxes, $currency)); } // The cart content is altered for display foreach ($cart_rules as &$cart_rule) { if ($cart_rule['free_shipping']) { $shipping_cost = Tools::displayPrice(0, $currency); $shipping_cost_float = 0; $cart_rule['value_real'] -= Tools::convertPrice($base_shipping_with_tax, $currency); $cart_rule['value_tax_exc'] = Tools::convertPrice($base_shipping_without_tax, $currency); } if ($cart_rule['gift_product']) { foreach ($products as $key => &$product) { if ($product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) { $product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_); $product['total'] = Tools::ps_round($product['total'] - $product['price'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_); if ($product['cart_quantity'] > 1) { array_splice($products, $key, 0, array($product)); $products[$key]['cart_quantity'] = $product['cart_quantity'] - 1; $product['cart_quantity'] = 1; } $product['is_gift'] = 1; $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_); $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'], (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_); } } } } $total_free_shipping = 0; if ($free_shipping = Tools::convertPrice(floatval(Configuration::get('PS_SHIPPING_FREE_PRICE')), $currency)) { $total_free_shipping = floatval($free_shipping - ($params['cart']->getOrderTotal(true, Cart::ONLY_PRODUCTS) + $params['cart']->getOrderTotal(true, Cart::ONLY_DISCOUNTS))); $discounts = $params['cart']->getCartRules(CartRule::FILTER_ACTION_SHIPPING); if ($total_free_shipping < 0) $total_free_shipping = 0; if (is_array($discounts) && count($discounts)) $total_free_shipping = 0; } $this->smarty->assign(array( 'products' => $products, 'cart_id' => (int)$params['cart']->id, 'hash' => md5(_COOKIE_KEY_.'recover_cart_'.(int)$params['cart']->id), 'customizedDatas' => Product::getAllCustomizedDatas((int)($params['cart']->id)), 'CUSTOMIZE_FILE' => Product::CUSTOMIZE_FILE, 'CUSTOMIZE_TEXTFIELD' => Product::CUSTOMIZE_TEXTFIELD, 'discounts' => $cart_rules, 'nb_total_products' => (int)($nbTotalProducts), 'shipping_cost' => $shipping_cost, 'shipping_cost_float' => $shipping_cost_float, 'show_wrapping' => $wrappingCost > 0 ? true : false, 'show_tax' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')), 'wrapping_cost' => Tools::displayPrice($wrappingCost, $currency), 'product_total' => Tools::displayPrice($params['cart']->getOrderTotal($useTax, Cart::BOTH_WITHOUT_SHIPPING), $currency), 'total' => Tools::displayPrice($totalToPay, $currency), 'order_process' => Configuration::get('PS_ORDER_PROCESS_TYPE') ? 'order-opc' : 'order', 'ajax_allowed' => (int)(Configuration::get('PS_BLOCK_CART_AJAX')) == 1 ? true : false, 'static_token' => Tools::getToken(false), 'free_shipping' => $total_free_shipping )); if (count($errors)) $this->smarty->assign('errors', $errors); if (isset($this->context->cookie->ajax_blockcart_display)) $this->smarty->assign('colapseExpandStatus', $this->context->cookie->ajax_blockcart_display); }  

En théorie et si je n’ai pas oublié de vous faire ajouter un override, on a ce qu’il nous faut pour passer à la partie Sendinblue.

Mise en place du scénario Sendinblue

Nous allons réaliser le scénario ci-après ensemble. Nous avons notre objectif mais avant le côté sexy du scénario nous devons préparer l’email.

Visuel du scénario qui va être réaliser

Création du template email

Aller dans l’onglet «Automation» de Sendinblue et cliquer sur «Templates d’emails»

Puis ajouter un nouveau template et préparer sa configuration pour pouvoir passer à l’onglet conception.

Pour le moment je n’ai pas trouvé de solution pour utiliser le système de template en glisser déposer de Sendinblue. les boucles (for each) qui permettent de boucler sur les données remontées par Prestashop dans Sendinblue ne sont pas applicables à un bloc complet et reste difficile à utiliser. Il est impossible de fabriquer un récapitulatif du panier de l’internaute éditable par tout un chacun pour l’instant. Pour le coup, nous allons créer un template email à partir d’un fichier html déjà fait que vous adapterez ensuite à votre goût.

Pour cela, utilisons un template responsive créé par un guru de l’email Ted Goas un simple CTRL + S sur cette page vous permettra de le récupérer (Github du projet Cerberus email).

Ouvrez-le avec un éditeur de texte classique et recherchez en fin de fichier les lignes suivantes

Juste avant insérez le code suivant

Puis importer le tout dans votre template Sendinblue

Vous devriez obtenir quelque chose qui ressemble à la capture suivante.

capture d'ecran de l'email en cours de réalisation

Vu comme cela ce n’est pas dingue mais ca fait le job !

J’ai mis en place une boucle de Sendinblue sur les paramètres qui arriveront de Prestashop.

Pour chaque ligne de produit dans le panier, on ajoutera une ligne de plus dans l’email

Et on aura un joli total à la fin.

Enfin, il manque un CTA (Call To Action) pour renvoyer l’internaute vers son panier comme nous l’avions évoqué dans le paragraphe : «Principe de fonctionnement».

Il faut ajouter encore un peu de code à la suite de ce que vous avez déjà ajouté :

Vous devez remplacer [Votre site web] par le domaine de votre site e-commerce prestashop.

Si vous avez bien travaillé, vous obtenez ceci :

capture d'ecran de l'email en cours de réalisation avec CTA

Pour en finir avec cette étape : on enregistre et on active le template.

Création du scénario

Allez dans l’onglet Automation, créez un nouveau scénario et choisissez scénario personnalisé.

Ajouter un point d’entrée > «Activité liée à votre site» > «Événement personnalisé»

Choisissez «Événements personnalisés (Track Event)» et ajoutez dans le champs «add_basket»

Puis faites «OK»

 

Ajoutez un autre point d’entrée > «Activité liée à votre site» > «Événement personnalisé»

Choisissez «Événement personnalisé (Track Event)» et ajoutez dans le champs «order_logged»

Puis faites «OK»

Ensuite cliquez sur le «+» en dessous des deux points d’entrée que vous avez créés

dans la partie «Condition», choisissez «Attendre jusqu’à» > «Activité du site web»

Sélectionnez l’option «Jusqu’à ce qu’un Track Event ait lieu» et ajoutez dans le champ «order_confirmation».

Sélectionnez la durée d’attente de votre panier abandonné (perso j’ai choisi une longue attente d’une journée)

Puis cliquez sur «OK»

Vous devriez avoir deux éléments qui s’affichent : «Oui» et «Non»

cliquez sur le «+» sous le «Non» pour Ajouter «Envoyer un email» puis sélectionnez votre template.

Vous pouvez vous envoyer une copie si vous le souhaitez pour tester ce que vos internautes reçoivent et ajouter une planification pour que les emails partent selon une tranche horaire spécifique.

Cochez la case «Utiliser les données des événements» pour personnaliser l’email,

sélectionnez l’option «Les données du dernier événement reçu»

et Ajoutez dans le champ «cart_created».

Puis faites «OK»

Et voilà !

Bon, il faut quand même que je vous explique ce que l’on vient de faire ensemble.

Vous venez de créer deux déclencheurs pour votre scénario. C’est à dire que vous dites à Sendinblue de faire entrer les internautes qui ont fait exécuter vos codes javascripts «add_basket» et/ou «order_logged» ensuite votre scénario met les internautes en attente pendant le temps que vous avez choisi (dans mon cas j’ai choisi une journée) si au bout de ce temps d’attente, l’internaute n’a pas envoyé d’action «order_confirmation» l’email de relance de panier abandonné sera envoyé avec les données du dernier envoi javascript «cart_created». L’email sera rempli avec les dernières informations du panier de l’internaute.

Quelques conseils :

  • Pour vos tests, vous pouvez ajouter une restriction sur uniquement votre email avant l’envoi des emails. Ainsi vous pourrez le tester sur vous avant de vous lancer dans le grand bain. Rien ne vous empêche du coup de mettre le délai d’attente à quelques secondes.
  • Pendant la phase de tests sur vos prospects et clients, je vous conseille d’être en copie des emails afin de vous assurer que ce qu’ils reçoivent correspond à ce que vous aviez prévu.
  • Ajoutez à votre template un tag du style «panier_abandon» pour pouvoir suivre facilement vos statistiques transactionnelles. Les envois de la partie automation apparaissent dans les logs de la partie transactionnelle de Sendinblue.
  • Pensez également à remplir un «utm_campaign» suffisamment intelligible pour vos mesures analytics
  • N’hésitez pas à vous munir d’un développeur et d’une bonne dose de courage avant de vous lancer dans l’aventure.

Et si jamais la peur vous bloque, vous pouvez toujours faire appel à nous pour votre projet.