How to count the number of consecutive days on which verified users accessed the website? My main problem is very similar to How to grant userpoints to users who perform a login 5 days consecutively?: I would like to keep track of the number of consecutive days on which verified users accessed the website. Therefore, I added an integer user field Consecutive days and created the following Rule that hooks into "visiting the website" (see How to hook into &quot;visiting the website&quot;?):

{ "rules_extra_consecutive_day_online" : {
    "LABEL" : "Extra consecutive day online",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "rules_scheduler" ],
    "ON" : { "init" : [] },
    "IF" : [
      { "user_has_role" : {
          "account" : [ "site:current-user" ],
          "roles" : { "value" : { "2" : "2" } }
        }
      },
      { "OR" : [
          { "data_is" : {
              "data" : [ "site:current-user:field-consecutive-days" ],
              "value" : "0"
            }
          },
          { "AND" : [
              { "data_is" : {
                  "data" : [ "site:current-user:last-access" ],
                  "op" : "\u003C",
                  "value" : "today midnight -1 second"
                }
              },
              { "data_is" : {
                  "data" : [ "site:current-user:last-access" ],
                  "op" : "\u003E",
                  "value" : "yesterday midnight"
                }
              }
            ]
          }
        ]
      }
    ],
    "DO" : [
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "site:current-user:field-consecutive-days" ],
            "op" : "+",
            "input_2" : "1"
          },
          "PROVIDE" : { "result" : { "new_streak" : "New streak" } }
        }
      },
      { "data_set" : {
          "data" : [ "site:current-user:field-consecutive-days" ],
          "value" : [ "new-streak" ]
        }
      },
      { "schedule" : {
          "component" : "rules_reset_consecutive_days",
          "date" : "+2 days midnight",
          "param_user" : [ "site:current-user" ]
        }
      },
    ]
  }
}


The scheduled Rules component at the end of the Rule resets Consecutive days to 0 if necessary:

{ "rules_reset_consecutive_days" : {
    "LABEL" : "Reset consecutive days",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : { "user" : { "label" : "User", "type" : "user" } },
    "IF" : [
      { "data_is" : {
          "data" : [ "user:last-access" ],
          "op" : "\u003C",
          "value" : "yesterday midnight -1 second"
        }
      }
    ],
    "DO" : [
      { "data_set" : {
          "data" : [ "user:field-consecutive-days" ],
          "value" : "0"
        }
      }
    ]
  }
}


This seems to work relatively well, but there is a catch: the Last access field is not updated at every page request. As a result, users can increase their Consecutive days during a few minutes right after midnight by refreshing the page again and again.

How can I fix this issue? Should I override the Last access field at every page request or is there an alternative way to correctly update Consecutive days?
Overriding the built-in Last access field is not possible with Rules, so I added a new user Date field Last day online that stores a day, month and year. Recall that I had already created another user integer field Consecutive days. Here is the magical Rule:

{ "rules_extra_consecutive_day_online" : {
    "LABEL" : "Extra consecutive day online",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "rules_scheduler" ],
    "ON" : { "init" : [] },
    "IF" : [
      { "NOT user_has_role" : {
          "account" : [ "site:current-user" ],
          "roles" : { "value" : { "1" : "1", "3" : "3" } }
        }
      },
      { "OR" : [
          { "data_is" : { "data" : [ "site:current-user:field-consecutive-days" ], "value" : "0" } },
          { "data_is" : {
              "data" : [ "site:current-user:field-last-day-online" ],
              "value" : "yesterday midnight"
            }
          }
        ]
      }
    ],
    "DO" : [
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "site:current-user:field-consecutive-days" ],
            "op" : "+",
            "input_2" : "1"
          },
          "PROVIDE" : { "result" : { "new_consecutive_days" : "New consecutive days" } }
        }
      },
      { "data_set" : {
          "data" : [ "site:current-user:field-consecutive-days" ],
          "value" : [ "new-consecutive-days" ]
        }
      },
      { "data_set" : {
          "data" : [ "site:current-user:field-last-day-online" ],
          "value" : "today midnight"
        }
      },
      { "schedule" : {
          "component" : "rules_reset_consecutive_days",
          "date" : "+2 days midnight",
          "param_user" : [ "site:current-user" ]
        }
      }
    ]
  }
}


This is what the Rule does in words:


First, check that the current user is verified, and make sure the user's Consecutive days field is zero or the user's Last day online is yesterday.
If the above requirements are satisfied, then increase the Consecutive days, change the Last day online to today and schedule the component Reset consecutive days.


Underneath is an export of the mentioned Rules component. It resets the Consecutive days field if the Last day online field is less than yesterday (which means that the user was not online on at least one day).

{ "rules_reset_consecutive_days" : {
    "LABEL" : "Reset consecutive days",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : { "user" : { "label" : "User", "type" : "user" } },
    "IF" : [
      { "data_is" : {
          "data" : [ "user:field-last-day-online" ],
          "op" : "\u003C",
          "value" : "yesterday midnight"
        }
      }
    ],
    "DO" : [
      { "data_set" : { "data" : [ "user:field-consecutive-days" ], "value" : "0" } }
    ]
  }
}