With the Drupal Commerce module, I created a new product type I use for selling points to my customers. The product has a custom field named “points” (field type integer) where I specify the amount of point to sell.

On checkout I grant the points to the user with this rule, using the Rules module (thanks to Vic, see "How do I sell points using a new product type?):

  1. Rule Event: on payment completed Action: loop through the order line-items. Each line-item has an action to call the next component with parameters of order and the line-item.
  2. Component Parameters: order, line-item Condition: data comparison line-item:type is Product (to expose line-item:commerce-product) Action: call next component with parameters of order and line-item:commerce-product
  3. Component Parameters: order, product Condition: data comparison product:type is Product (to expose the product:field-points-to-add) • Action: add userpoints, number to add being product:field-points-to-add

The problem comes when the quantity of the products sold is more than 1 because the action loops only through line-item and not through line-item:quantity.

Any suggestion for looping through line-item:quantity?

  • Possible workaround: disallow buying many of the same. Create products for "bundles" of 5, 10, 20, 50 points and so on, with slightly deceasing cost per point, and people will not even try to add more than one.
    – Mołot
    Sep 19, 2013 at 8:18
  • That's why it's only a comment, and not posted as an answer. I would like to see it solved too as it might have more uses. I just thought that this suggestion may help you to get things up and running before issue gets solved the "proper way".
    – Mołot
    Sep 19, 2013 at 8:31

1 Answer 1


Consider this Rules Component (in Rules export format, use the Rules UI to import it in your own site):

{ "rules_grant_user_points_multiple_times" : {
    "LABEL" : "Grant user points multiple times",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "userpoints_rules" ],
      "points_to_grant" : { "label" : "Points to grant", "type" : "integer" },
      "quantity" : { "label" : "Quantity", "type" : "integer" }
    "DO" : [
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "points-to-grant" ],
            "op" : "*",
            "input_2" : [ "quantity" ]
          "PROVIDE" : { "result" : { "calculated_points" : "Calculated points" } }
      { "userpoints_action_grant_points" : {
          "user" : [ "site:current-user" ],
          "points" : [ "calculated-points" ],
          "tid" : "0",
          "entity" : [ "site:current-user" ],
          "operation" : "Insert",
          "display" : "1",
          "moderate" : "default"

Some more details about this Rules Component:

  • It uses 2 parameters (both "integer"), i.e.:
    • Points to grant, which is like your custom field named “points”.
    • Quantity, which is like your quantity of the products sold.
  • Rules Actions:
    • Calculate a new variable (= calculated_points), which is simply a multiplication of the above 2 parameters.
    • Grant user points for an amount equal to ... euh ... indeed: calculated_points (adapt the details of the actual transaction to fit your needs).

These User Points will be granted to the "current user". Optionally you could just make that yet another parameter for the Rules Component also. I.e. if "current user" is not the customer who bought the quantity of products (which would allow one customer to buy such points for another user should you want to allow that, similar to a gift-card).

With that, all that's left is to finds the right spot in your existing Rules logic (related to checkout), to use the above Rules Component.

Easy, no?

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.