Drupal Commerce AdWords-module: verschil tussen versies

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen
Regel 199: Regel 199:
 
* '''Selectiemechanisme''' om de dankjewel-pagina te selecteren
 
* '''Selectiemechanisme''' om de dankjewel-pagina te selecteren
 
* '''Plaatsingsmechanisme''' om de tag te plaatsen
 
* '''Plaatsingsmechanisme''' om de tag te plaatsen
* '''Format & executie:''' Dit betreft een JavaScript-tag, en dat ding moet uitgevoerd worden, en niet bv. afgebeeld worden alsof het gewoon tekst is.
+
* '''Executie:''' Dit betreft een JavaScript-tag, en dat ding moet uitgevoerd worden, en niet bv. afgebeeld worden alsof het gewoon tekst is.
  
 
=== hook_footer (Drupal 6) ===
 
=== hook_footer (Drupal 6) ===

Versie van 18 feb 2017 12:03

In 2013/2014 is module uc_adword geïmplementeerd: Dynamische conversion-tracking voor Übercart 2/Drupal 6. Dit is geen 'complete' module en bevat zelfs geen grafische interface, maar hij doet precies waar-ie voor bedoeld is. De module is vrijgegeven onder de GPL V2.

Eind 2016 was er geen ontkomen meer aan: De module moest omgezet worden naar Drupal 7/Drupal Commerce 1.x, onder de naam commerce_adwords.

uc_adwords: Hoe het werkt

De module declareert twee functies die dankzij de juiste hooks rondom de dankjewel-pagina hun ding doen. Je hoeft dus geen code in te voegen in blocks of pagina's. In de code kun parameter PRODUCTS_ONLY gebruiken om te bepalen dat het orderbedrag in- of exclusief vervoerskosten overgenomen moet worden. Iets meer in detail:

  • uc_adwords_order() detecteert nieuwe orders, en slaat de order-id op in een custom sessie-variablee
  • uc_adwords_footer() detecteert de dankjewel-pagina. Haalt de sessie-variabele op, roept de tag-functie aan, en output de tag naar de footer
  • add_adwords_js() Genereer en retourneer AdWords-tag.

Welk bedrag precies?

Orderbedrag minus vrachtkosten minus BTW:

20151009-01.png
20151009-02.png

Drupal 7: Overzicht bestaande modules

Ik geloof niet dat er een module bestaat die dit dynamisch doet:

Debugging

Event registration

Gebruik drush fn-hook om een overzicht te krijgen van geregistreerde hooks. Bv.:

drush fn-hook commerce_checkout_complete

Enter the number of the hook implementation you wish to view.
 [0]  :  Cancel           
 [1]  :  commerce_adwords 
 [2]  :  commerce_cart

1

// file: /var/www/kbo215.dvb/sites/all/modules/commerce_adwords/commerce_adwords.module, lines 7-10
function commerce_adwords_commerce_checkout_complete($order)
{
	print phpinfo();
}

Event-code uitvoeren

Het resultaat van de code hiernaast

Hier komt de truuk: print phpinfo(); werkt niet! Blijkbaar zijn er events waarbij je niet op deze manier uitvoer naar het scherm kunt forceren! Een voorbeeld van wat wel werkt:

// commerce_checkout_complete
/////////////////////////////////////////////
//
function commerce_adwords_commerce_checkout_complete($order)
{
	dpm($order);
	// print "<br><br><br> commerce_checkout_complete";
	// print phpinfo();
}

Tag invoegen - hook_init

Dit werkt:

<?php

/////////////////////////////////////////////
// hook - commerce_checkout_complete($order)
/////////////////////////////////////////////
//
// Werkt niet. Zie http://wiki.devliegendebrigade.nl/Drupal_Commerce_AdWords-module
//
// function commerce_adwords_commerce_checkout_complete($order)
// {
//	print phpinfo();
// }	

/////////////////////////////////////////////
// hook_init()
/////////////////////////////////////////////
//
// Dit is de basis
// 
// * hook_init() is run on every page load except for cached pages, 
//   so depending on your use case that might be an option.
// * (http://drupal.stackexchange.com/questions/33789/how-to-run-check-on-each-page-load)
//
// function commerce_adwords_init()
// {
// 	print "commerce_adwords_init";
// }	

/////////////////////////////////////////////
// commerce_adwords_init()
/////////////////////////////////////////////
//
function commerce_adwords_init()
{
	if (arg(0)=='checkout' && arg(2)=='complete')
	{
		print phpinfo();
	}
}

Nieuwe order onderscheppen

Het gaat om dit event
hook_commerce_order_presave vuurt op het moment dat je iets toevoegt aan de winkelwagen
Order review-pagina: hook_commerce_order_presave en hook_entity_insert
Checkout complete-pagina: hook_commerce_checkout_complete, hook_commerce_order_presave, hook_init en hook_commerce_order_status_info. Deze eerste is het meest relevant

Dit zijn zoal de hooks die in aanmerking leken te komen om een nieuwe order te onderscheppen. Dit ruime lijstje ontstond, omdat ik niet effectief debugde (zie hierboven):

  • hook_commerce_checkout_complete - Lijkt niet te werken. Zie hieronder
  • hook_entity_insert [3]
  • hook_entity_update
  • hook_commerce_order_presave()
  • hook_commerce_order_status_update[4]
  • hook_commerce_order_state_info [5] - Waarschijnlijk niet
  • hook_commerce_order_status_info [6] - Actief op elke pagina. Bruikbaar?

commerce_order_checkout_complete is het juiste event. Dat zie je ook terug in de eerste regels van deze code-export van het checkout_completetion_email_send-event:

{ "commerce_checkout_order_email" : 
   {
      "LABEL" : "Send an order notification e-mail",
      "PLUGIN" : "reaction rule",
      "WEIGHT" : "4",
      "OWNER" : "rules",
      "TAGS" : [ "Commerce Checkout" ],
      "REQUIRES" : [ "rules", "commerce_checkout" ],
      "ON" : { "commerce_checkout_complete" : [] },
...

Zie de appendix voor alle hooks bij elkaar.

order_id of order_number?

Drupal Commerce kent een order_id en een order_number. Geen idee wat het verschil is. Ik houd het erop, dat ik deze eerste nodig heb.

Order_number opslaan

Hebbes: order_number is inderdaad '27763

Tjakka:

/////////////////////////////////////////////
// Niewe order onderscheppen
/////////////////////////////////////////////
//
function commerce_adwords_commerce_checkout_complete($order)
{
	$_SESSION['adwords_commerce_order_number'] = $order->order_number;
	dpm($order);
	dpm($order->order_number);
	dpm($_SESSION['adwords_commerce_order_number']);
}

In de schermafdruk hiernaast zie je dat de onderste twee dpm-commando's functioneren, want het order_number is inderdaad 27763.

Orderbedrag uitlezen

Übercart heeft de functie uc_order_get_total($order, TRUE); om ordergegevens boven water te toveren als je het $order-object opgeeft. Hoe doe je dat in Drupal Commerce?

Uit het order-object peuteren

Yep: Ik kan het uit het order-object peuteren, maar da's nogal lastig + instabiel. Dat kan vast beter.

API-calls?

Voorbeelden van mogelijk relevante functies:

https://drupalcommerce.org/discussions/397/get-order-total:

$order = commerce_order_load($order_id);
$wrapper = entity_metadata_wrapper('commerce_order', $order);
$total = $wrapper->commerce_order_total->amount->value();
$currency_code = $wrapper->commerce_order_total->currency_code->value();

Output tag to page

Nu nog die tag op de betreffende pagina serveren. Dat heeft een paar onderdelen, die vaak met elkaar verweven zijn:

  • Hook om een pagina aan te passen
  • Selectiemechanisme om de dankjewel-pagina te selecteren
  • Plaatsingsmechanisme om de tag te plaatsen
  • Executie: Dit betreft een JavaScript-tag, en dat ding moet uitgevoerd worden, en niet bv. afgebeeld worden alsof het gewoon tekst is.

hook_footer (Drupal 6)

In Drupal 6 werd hook_footer gebruikt om het script te incorporeren op een pagina.https://api.drupal.org/api/drupal/developer!hooks!core.php/function/hook_footer/6.x:

Insert closing HTML.

This hook enables modules to insert HTML just before the \</body\> closing tag of web pages. 
This is useful for adding JavaScript code to the footer and for outputting debug information. 
It is not possible to add JavaScript to the header at this point, and developers wishing to 
do so should use hook_init() instead.

In Drupal 7 bestaat hook_footer echter niet meer [7].

drupal_add_js

drupal_add_js - https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_add_js/7.x

$page_bottom, $page_top, hook_page_build, hook_page_alter

$page_bottom, $page_top, hook_page_build(), hook_page_alter() - https://www.drupal.org/node/224333#hook_footer

Appendix: Broncode uc_adwords

uc_adwords.info

name = uc_adwords
description = Implements dynamic conversion tracking for adwords in ubercart
version = 6.x-0.1
core = 6.x
package = Custom
files[] = uc_adwords.module

uc_adwords.install

Er is geen installatie-procedure:

<?php

uc_adwords.module - 2014

<?php

define('PRODUCTS_ONLY', FALSE); // If set to TRUE google_conversion_value will be products only (without shipping costs)

function uc_adwords_footer () {
  // Check to see if we are at the order completion page.
  if (arg(0) == 'cart' && arg(1) == 'checkout' && arg(2) == 'complete') {
    // If we can load the order...
    if ($order = uc_order_load($_SESSION['uc_adwords_order_id'])) {
      $output = add_adwords_js($order);
    }
    // Clean out the session variable.
    unset($_SESSION['uc_adwords_order_id']);
  }
  return $output;
}

/**
 * Implementation of hook_order().
 */
function uc_adwords_order($op, &$arg1, $arg2) {
  switch ($op) {
    case 'new':
      // Store the order ID for later use.
      $_SESSION['uc_adwords_order_id'] = $arg1->order_id;
      break;
  }
}

function add_adwords_js ($order) {
	//global $_google_adwords_footer_script;

	$script = '';

	// google adwords parameters
        //
	$google_conversion_id = 986212345;
	$google_conversion_language = "en";
	$google_conversion_format = "2";
	$google_conversion_color = "ffffff";
	$google_conversion_label = "FM3zCM-12345qc2m1gM";
	$google_remarketing_only = false;

	// conversion value
	// ================
	//
	// Value PRODUCTS_ONLY (boolean)
	//
	// true : Only value of products incorporated, ex. transportation cost
	// false: Complete order amount incorporated
	//
	$PRODUCTS_ONLY = True;

	if (PRODUCTS_ONLY)
		$google_conversion_value = uc_order_get_total($order, TRUE);
	else {
		$google_conversion_value = $order->order_total;
	}
	$google_conversion_value = uc_currency_format($google_conversion_value, FALSE, TRUE, '.');

	// google adwords script
  $script = '';    
  $script .= "\n" . '<!-- Google Code for Order Complete scherm Conversion Page -->' . "\n";
  $script .= '<script type="text/javascript">' . "\n";
  //$script .= '<!--' . "\n";
  $script .= ' /* <![CDATA[ */' . "\n";
  $script .= '    var google_conversion_id = '. $google_conversion_id .';' . "\n";
  $script .= '    var google_conversion_language = "'. $google_conversion_language .'";' . "\n";
  $script .= '    var google_conversion_format = "'. $google_conversion_format .'";' . "\n";
  $script .= '    var google_conversion_color = "'. $google_conversion_color .'";' . "\n";
  $script .= '    var google_conversion_label = "'. $google_conversion_label .'";' . "\n";
  $script .= '    var google_conversion_value = "'. $google_conversion_value .'";' . "\n";
  $script .= '    var google_remarketing_only = "'. $google_remarketing_only .'";' . "\n";
  $script .= ' /* ]]> */ ' . "\n";
  $script .= '</script>' . "\n";
  $script .= '<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">' . "\n";
  $script .= '</script>' . "\n";
  $script .= '<noscript>' . "\n";
  $script .= '<div style="display:inline;">' . "\n";
  $script .= '<img height="1" width="1" border="0" src="https://www.googleadservices.com/pagead/conversion/' . $google_conversion_id . '?value='. $google_conversion_value .'&label='. $google_conversion_label .'&guid=ON&script=0" alt=""/>' . "\n";
  $script .= '</div>' . "\n";
  $script .= '</noscript>' . "\n";

	return $script;  
}

uc_adwords.module - 2015

Wijzigingen:

  • Google Tag Assistant suggereerde dat geldbedragen numerieke waardes dienen te zijn, en geen strings
  • Voorzien van commentaar
<?php

define('PRODUCTS_ONLY', FALSE); // If set to TRUE google_conversion_value will be products only (without shipping costs)

/////////////////////////////////////////////////////////////////////////
// uc_adwords_footer() 
/////////////////////////////////////////////////////////////////////////
//
// Output the AdWords Conversion-tag at the checkout completion page
//
// * The hook is 'footer'
// * Additionally, check that we're on the checkout completion page
// * Additionally, check that we can load the current order
// * Call function add_adwords_js($order)
//
function uc_adwords_footer () 
{
   if (arg(0) == 'cart' && arg(1) == 'checkout' && arg(2) == 'complete') 
   {
      // If we can load the order...
      if ($order = uc_order_load($_SESSION['uc_adwords_order_id'])) 
      {
         $output = add_adwords_js($order);
       }
       // Clean out the session variable.
       unset($_SESSION['uc_adwords_order_id']);
   }
   return $output;
}

/////////////////////////////////
// uc_adwords_order()
/////////////////////////////////
//
// Intercept any new order and store order-ID in a custom session variable
//
// * Hook = "order": http://www.ubercart.nl/docs/api/hook_order
// * $op:   De action that is being performed
// * $arg1: Order-object
// * $arg2: Eventueel additioneel argument bij $arg1

function uc_adwords_order($op, &$arg1, $arg2) 
{
   switch ($op) 
   {
      case 'new':

         // Store the order ID in a session variable for later use
         //
         $_SESSION['uc_adwords_order_id'] = $arg1->order_id;
         break;
   }
}

/////////////////////////////////
// add_adwords_js()
/////////////////////////////////
//
// Generate tag
//
function add_adwords_js ($order) 
{
   //global $_google_adwords_footer_script;

   $script = '';

   // google adwords parameters
   //
   $google_conversion_id = 986212345;
   $google_conversion_language = "en";
   $google_conversion_format = "2";
   $google_conversion_color = "ffffff";
   $google_conversion_label = "FM3zCM-12345qc2m1gM";
   $google_remarketing_only = false;

   // conversion value
   // ================
   //
   // Value PRODUCTS_ONLY (boolean)
   //
   // true : Only value of products incorporated, ex. transportation cost
   // false: Complete order amount incorporated
   //
   $PRODUCTS_ONLY = True;

   if (PRODUCTS_ONLY)
      $google_conversion_value = uc_order_get_total($order, TRUE);
   else 
   {
      $google_conversion_value = $order->order_total;
   }

   $google_conversion_value = uc_currency_format($google_conversion_value, FALSE, TRUE, '.');

   // Assemble Adwords tag
   // ====================
   //
   $script = '';    
   $script .= "\n" . '<!-- Google Code for Order Complete scherm Conversion Page -->' . "\n";
   $script .= '<script type="text/javascript">' . "\n";
   //$script .= '<!--' . "\n";
   $script .= ' /* <![CDATA[ */' . "\n";
   $script .= '    var google_conversion_id = '. $google_conversion_id .';' . "\n";
   $script .= '    var google_conversion_language = "'. $google_conversion_language .'";' . "\n";
   $script .= '    var google_conversion_format = "'. $google_conversion_format .'";' . "\n";
   $script .= '    var google_conversion_color = "'. $google_conversion_color .'";' . "\n";
   $script .= '    var google_conversion_label = "'. $google_conversion_label .'";' . "\n";
   $script .= '    var google_conversion_value = '. $google_conversion_value .';' . "\n";
   $script .= '    var google_remarketing_only = "'. $google_remarketing_only .'";' . "\n";
   $script .= ' /* ]]> */ ' . "\n";
   $script .= '</script>' . "\n";
   $script .= '<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">' . "\n";
   $script .= '</script>' . "\n";
   $script .= '<noscript>' . "\n";
   $script .= '<div style="display:inline;">' . "\n";
   $script .= '<img height="1" width="1" border="0" src="https://www.googleadservices.com/pagead/conversion/' . $google_conversion_id . '?value='. $google_conversion_value .'&label='. $google_conversion_label .'&guid=ON&script=0" alt=""/>' . "\n";
   $script .= '</div>' . "\n";
   $script .= '</noscript>' . "\n";

   return $script;  
}

Appendix: Nieuwe order onderscheppen (Drupal 7)

Let op: dpm($order) werkt. Print-opdrachten werken vaak niet!

<?php

/////////////////////////////////////////////
// Niewe order onderscheppen
/////////////////////////////////////////////

// entity_insert
/////////////////////////////////////////////
//
function commerce_adwords_entity_insert($entity, $type)
{
	// dpm($order);
	// print "<br><br><br> entity_insert";
	// print phpinfo();
}

// entity_presave
/////////////////////////////////////////////
//
function commerce_adwords_entity_presave()
{
	// dpm();
	print "<br><br><br> entity_presave";
	// print phpinfo();
}

// entity_update
/////////////////////////////////////////////
//
function commerce_adwords_entity_update($entity, $type)
{
	// dpm();
	print "<br><br><br> entity_update";
	// print phpinfo();
}

// commerce_checkout_complete
/////////////////////////////////////////////
//
function commerce_adwords_commerce_checkout_complete($order)
{
	dpm($order);
	// print "<br><br><br> commerce_checkout_complete";
	// print phpinfo();
}

// Overige events
/////////////////////////////////////////////
//
function commerce_adwords_commerce_order_presave($order)
{
	dpm($order);
	// print "<br><br><br> commerce_order_presave";
	// print phpinfo();
}

function commerce_adwords_order_state_info()
{
	dpm($order);
	// print "<br><br><br> commerce_adwords_commerce_order_presave";
	// print phpinfo();
}

function commerce_adwords_commerce_order_status_update()
{
	dpm($order);
	// print "<br><br><br> commerce_order_status_update";
	// print phpinfo();
}

function commerce_adwords_commerce_order_status_info()
{
	// dpm($order);
	print "<br><br><br> commerce_order_status_info";
	// print phpinfo();
}

function commerce_adwords_init()
{
	if (arg(0)=='checkout' && arg(2)=='complete')
	{
		print "<br><br><br> commerce_adwords_init - checkout-completed-page<br>";
	}
}	

Appendix: Broncode Drupal Commerce AdWords

<?php

// ----------------------------------------------------------------------------
// Store ID of newly created order in a session variable
// ----------------------------------------------------------------------------
//
function commerce_adwords_commerce_checkout_complete($order)
{
	$_SESSION['adwords_commerce_order_number'] = $order->order_number;
	// dpm($order);
	// dpm($order->order_number);
	// dpm($_SESSION['adwords_commerce_order_number']);
}

// ---------------------------------------------------------------------------------
// Output tag to completed-page
// ---------------------------------------------------------------------------------
//

function commerce_adwords_page_alter(&$page)
{

	if (substr(current_path(),0,8)=="checkout" and substr(current_path(),-8)=="complete")
	{
	
		$order = commerce_order_load($_SESSION['adwords_commerce_order_number']);
		$tag=create_tag($order);

		dpm
		(
			$order,
			"Function commerce_adwords_page_alter"
		);

		$page['footer']['block_3'] = array
		(
	     	'#markup' => $tag
		);	
	}
}
		
// ----------------------------------------------------------------------------
// Create tag ($order)
// ----------------------------------------------------------------------------
//
// Input: Order-object for the given order_number
//
function create_tag ($order) 
{

	// Reset script
	// ------------------------------
	//
	$script = '';

	// Set AdWords parameters
	// ---------------------------------
	//
	$google_conversion_id = 981232345;
  	$google_conversion_language = "en";
  	$google_conversion_format = "2";
  	$google_conversion_color = "ffffff";
  	$google_conversion_label = "F12345-12345qc2m1gM";
  	$google_remarketing_only = false;

	// Set conversion value
	// ----------------------------------
	//
	$wrapper = entity_metadata_wrapper('commerce_order', $order);
	$order_total = $wrapper->commerce_order_total->amount->value();
	$google_conversion_value = intval(($order_total/1.21-326))/100;

	// dpm($order_total);	// Correct
	// dpm($google_conversion_value); // Correct, behalve afrondfout

   // Assemble Adwords tag
   // ------------------------------
   //
   $script = '';    
   $script .= "\n" . '<!-- Drupal Commerce AdWords conversion tag -->' . "\n";
   $script .= '<script type="text/javascript">' . "\n";
   //$script .= '<!--' . "\n";
   $script .= ' /* <![CDATA[ */' . "\n";
   $script .= '    var google_conversion_id = '. $google_conversion_id .';' . "\n";
   $script .= '    var google_conversion_language = "'. $google_conversion_language .'";' . "\n";
   $script .= '    var google_conversion_format = "'. $google_conversion_format .'";' . "\n";
   $script .= '    var google_conversion_color = "'. $google_conversion_color .'";' . "\n";
   $script .= '    var google_conversion_label = "'. $google_conversion_label .'";' . "\n";
   $script .= '    var google_conversion_value = '. $google_conversion_value .';' . "\n";
   $script .= '    var google_remarketing_only = "'. $google_remarketing_only .'";' . "\n";
   $script .= ' /* ]]> */ ' . "\n";
   $script .= '</script>' . "\n";
   $script .= '<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">' . "\n";
   $script .= '</script>' . "\n";
   $script .= '<noscript>' . "\n";
   $script .= '<div style="display:inline;">' . "\n";
   $script .= '<img height="1" width="1" border="0" src="https://www.googleadservices.com/pagead/conversion/' . $google_conversion_id . '?value='. $google_conversion_value .'&label='. $google_conversion_label .'&guid=ON&script=0" alt=""/>' . "\n";
   $script .= '</div>' . "\n";
   $script .= '</noscript>' . "\n";

	// Return script
	// ------------------
	//
 	return $script;  
}

Zie ook

Bronnen

hook_commerce_checkout_complete

Order uitlezen

Order uitlezen » hook_entity_insert & hook_entity_update

Order uitlezen '