Users cannot see what size or color shirt they purchased in the email receipt because tokens won't print the attribute fields provided by Commerce Product Attributes / Commerce Pricing Attributes / Commerce Product Option combo.

  1. User selects shirt size: XL and color: Green
  2. Both fields can be previewed during checkout.
  3. Email receipt received doesn't show any attributes, user cannot check what size/color they ordered. (All this can be achieved using default CCK fields under product type, but we're using the combination mentioned above for multiple reasons, many products got different option sets to chose from and certain attributes selected adds extra price to total, like eg size: XXXL costs extra $3+ and this cannot be achieved with default fields).

One of the tokens I found is like eg. [commerce-order:commerce-line-items:0:commerce-pricing-attributes] and email on checkout prints it like this:

Product: BK Test


Also more tokens available at admin/help/token like eg.: Attributes [commerce-line-item:commerce-product:field_attributes] Pricing Attributes field. and combining them with [commerce-order:commerce-line-items:0:commerce-product] won't work, already tried dozens of variations.

E.g. in Order's view page I addded the view Commerce Line Item: Product Attributes and it displays correctly.

enter image description here

How to print this in the email receipt?

  • Have you tried write your own token or write a custom function with order parameter?
    – cobenash
    Jan 14, 2019 at 14:31
  • It's easy using entity_metadata_wrapper to find what you want and print it.
    – cobenash
    Jan 14, 2019 at 14:31
  • Well, all the tokens already exist in the token help list for each and every field, they just won't print if it's order/line item. Jan 14, 2019 at 14:50
  • i think can you use hook_tokens
    – vinhdv
    Jan 16, 2019 at 2:45

2 Answers 2


install views rules module, make a views-rules of orders, you will need OID as a contextual filter, add it as allways, then in middle column, in parameters settings set your OID as:integer, add all fields/attributes you wish, now in middle column settings, set your fields/attributes values as text, choose 'use rendered output'.

Then in your send-email-to-customer rule, add a views-rule with your new view, actions: fecth entity by id:ORDER with your variable OID, now you have all fields/attributes you added avilable as tokens, built your email body like: thanks [user:name], your order [OID] is in proccess, you bought : T-shirt [tshirt:value], T-shirt-size: [tshirt-size:value], ............. .

if you can not use HTML tags, here is an exported rules_action_info() rules code that i used in one site, adds a new action: build-email-body, it shows you how to built a row for a 'nice' html look alike. if you need this feature, you will need to make a custom module called: rulesbodyemail, change all $variables and code as needed, take a close look how is built variable: $text_formatted_body, and is how is returned.

 * Implement hook_rules_action_info()
 * Declare any meta data about actions for Rules

 function rulesbodyemail_rules_action_info() {

 $actions = array(
'buitl_email_body' => array(
    'label' => t('build-email-body'),
    'group' => t('cadena'),

    'parameter' => array(

      'node_id' => array(
              'type' => 'integer',
              'label' => t('node id'),

      'parcialidad_title' => array(
              'type' => 'text',
              'label' => t('parcialidad_title'),

      'parcialidad_monto' => array(
              'type' => 'decimal',
              'label' => t('parcialidad monto'),
      'parcialidad_cliente' => array(
              'type' => 'text',
              'label' => t('cliente'),

      'parcialidad_fecha' => array(
              'type' => 'date',
              'label' => t('parcialidad fecha'),
      'parcialidad_aseguradora' => array(
              'type' => 'text',
              'label' => t('cia aseguradora'),

      'parcialidad_ramo' => array(
              'type' => 'text',
              'label' => t('ramo'),

        'parcialidad_cobertura' => array(
                'type' => 'text',
                'label' => t('cobertura'),

        'parcialidad_fecha_formateada' => array(
                'type' => 'text',
                'label' => t('feha formateada'),


    'provides' => array(
        'text_formatted_body' => array(
                'type' => 'text',
                'label' => t('text_formatted body'),
                'wrap' => TRUE,
                //'format' => 'full_html'
  return $actions;

 } // fin de actions_info

// rules function procesar row
function buitl_email_body($node_id, $parcialidad_title, $parcialidad_monto,
$parcialidad_cliente, $parcialidad_fecha, $parcialidad_aseguradora,
$parcialidad_ramo, $parcialidad_cobertura, $parcialidad_fecha_formateada) {

// variable $hoy esta en UNIX
$hoy = time();
$formatted_hoy = date('j/M/y', $hoy);

  //drupal_set_message($parcialidad_fecha_int . ' $parcialidad_fecha ', 'status', FALSE);
  //drupal_set_message($formatted_fecha . ' $formatted_fecha ', 'status', FALSE);

  //prepara las variables y calcula dias vencidos
  $parcialidad_fecha_int = strip_tags($parcialidad_fecha);
  $hoy_int = (int)$hoy;
  $fecha_int = (int)$parcialidad_fecha_int;
  $diff = $hoy_int - $fecha_int;
  $diff = round($diff/86400);

  // formato fecha y $ pesos

  $monto_format = "$".number_format($parcialidad_monto, 2);
  $formatted_fecha = date('j/M/y', $parcialidad_fecha_int);

  //hace el render del row
  $text_formatted_body =

  ▲ PARCIALIDAD ▲ $parcialidad_cliente

    Parcialidad: $parcialidad_title
    Monto:  $monto_format
    Venció: $formatted_fecha; Días vencidos: $diff

    Aseguradora : $parcialidad_aseguradora
    Ramo: $parcialidad_ramo; Cobertura: $parcialidad_cobertura

  " ;

  //return $text_formatted_body
  return array('text_formatted_body' => $text_formatted_body);

  } // fin de funcion rules procesar row

it returns this as the email body:

enter image description here

image of rule to send emails:

enter image description here

image of body email value

enter image description here

  • 1
    Insane solution, holy moly, can't believe this works, this Views Rules module is really powerful and it's not updated since 2k12! And for formatting, I didn't need custom module, just add internal <style></style> at the top of the body above all the tokens in the rules. Thanks for helping. Jan 20, 2019 at 11:45
  • hi @pinueve, it sends separate email for each line item in the cart. So if ordering 5 items, user gets 5 emails with each product. Should be all products in one email. Can you make a screenshot of your rules setup? Jan 21, 2019 at 12:49
  • it could be that your rules-view is returning same order several times, in query settings toggle 'unique results', or in rule-email do send email outside the views-loop, to do this, add a text-token variable first and outside views-loop, built body as you did, and asign your text-token-variable with email-body value, and send email with variable-token, let me know if this helps.
    – pinueve
    Jan 21, 2019 at 16:26
  • i added images of my rule and email body value.
    – pinueve
    Jan 21, 2019 at 16:37
  • Here's mine i.imgur.com/apQ5IUx.png everything you move outside loop does not get picked up, no tokens available and email is empty. I do not see the fetch ID part in your screenshot and seem like yours using author ID and not order ID and you have multiple data fields. I ticked the disctinct in the view, but I don't think it's the problem, the emails are not dupes, it sends separate email for separate line item in the order with its details. Jan 21, 2019 at 17:59

 * Implements hook_token_info().
function mymodule_token_info(){
    $info['tokens']['commerce-order']['line_item_detail'] = array(
        'name' => t('Line Item Product Detail List'),
        'description' => t('List all the Product Line Item Detail of the order')
    return $info;

 * Implements hook_tokens().
function mymodule_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();

  if($type == 'commerce-order'){
    $order = $data['commerce-order'];
    $order_wrapper = entity_metadata_wrapper('commerce_order',$order);
    $lineItems = $order_wrapper->commerce_line_items->value();
    $lineItemArray = array();
    foreach($lineItems as $key => $value){
        $line_item_wrapper = entity_metadata_wrapper('commerce_line_item',$value);
            $product_title = $line_item_wrapper->commerce_product->title->value();
            $quantity = $line_item_wrapper->quantity->value();
            $lineItemArray[] =  $product_title.' x '.$quantity;

    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'line_item_detail':
            $variables = array(
                'items' => $lineItemArray,
                'type' => 'ul',
            $replacements[$original] = theme('item_list', $variables);
  return $replacements;

This is the sample code.

You can modify the result you want at hook_tokens().

I hope this will help you.

  • this shows only title and quantity. I tried adding product_attributes or simple sku I get error Unable to get a data value. Error: Unknown data property sku. Jan 19, 2019 at 10:48
  • I was missing ->commerce_product-> for SKU to be printed, but still can't figure how to print product attributes like in the given screenshot. Jan 19, 2019 at 15:22
  • product_attributes (seen in screenshot, displays correct via views) gives error mentioned before and field field_custom_attributes that is Pricing Attributes field type prints Array and notice Array to string conversion line 30 Jan 19, 2019 at 15:38
  • you can use follow this drupal.org/docs/7/api/entity-api/entity-metadata-wrappers, and then you can get what you want. you can use $wrapper->commerce_price->amount->value(), and change amount to decimal by using commerce_currency_amount_to_decimal($amount,$currency);
    – cobenash
    Jan 19, 2019 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.