How do I count the number of pages a user has seen on my site, and force them to log in after a certain amount

Background

Gating unauthenticated end-user’s ability to view site content based on the activity of such users is a difficult problem to solve reliably, owed to the design of web technologies as a whole.

To the best of my knowledge, WordPress core provides no features which require any such functionality, and so there are no core APIs which are specifically designed to facilitate it.

Authentication mechanisms (such as those used to “log in”) enable us to make a plausible assertion that an end-user is associated with a particular user record stored on our site, which is what allows sites to store and leverage data related to that user. But unauthenticated users do not provide a site with any particularly useful form of identification – so how can associate data with them?


General Solutions

There are a few conventional ways to work around the problem – but all of them come with their own flaws and caveats.

Don’t.

One alternative to trying to keep track of unauthenticated users is simply not to. By this, I mean you either rework your content restriction strategy to remove the necessity to do so, or provide some other means for end-users to authenticate – ideally one which might require very low effort on the end-user’s part and lower the barrier to registration.

The former might mean that instead of trying to limit how many articles an unauthenticated user can view, you only provide them with a portion of each article, or maybe create a classification of article which will always be publicly available while limiting the rest.

An example of the latter (or perhaps both) would be the publishing platform Medium, where some content is restricted to only being accessible to authenticated users, but registering and authenticating is little more than a few clicks thanks to a Single Sign-On mechanism (e.g. “Sign in with Google”). The site is then able to more definitively track and restrict the content views of it’s free users.

The lack of any sort of extended registration form generally lowers the barrier to entry, as does the ability for an end-user to use an account that they already have instead of creating a new one for the site. But since it does still require a user to associate an identity with the site, the barrier’s still quite a bit higher than not requiring authentication at all, which can eat into traffic and conversion rates.

Client Data

A very common solution is to store either some sort of “session ID”/identifier or the data itself in the end-user’s client. This is usually in the form of a cookie which is automatically sent to the server along with every request which that particular browser will make.

While it’s possible to effectively prevent tampering with cookie data by either “signing” the data in a cookie (by including a server-generated hash of the data within the cookie) or entirely encrypt the cookie data, cookies are usually limited to the client to which they were delivered, and in the case of web browsers there’s no way to prevent an end-user from deleting the cookie. In this case, than means that unauthenticated visitors can “reset” their view count by changing browsers, devices, or disabling or deleting the cookie.

Nonetheless it’s still a relatively popular mechanism for view-gating content, and is often seen on many prominent subscription news sites such as The Washington Post and Bloomberg.

Example

A the logic you’ve described could be implemented with a cookie roughly as follows.

wpse408666_handle_visitor_views_cookie() {
  $view_cookie="wpse408666_content_views"; // Cookie key.
  $cookie_ttl  = 24 * 3600; // 24 hours (in seconds).
  $max_views   = 6;

  // Don't process the views cookie for logged in users.
  if( get_current_user_id() > 0 )
    return;

  // Only handle the views cookie for posts and CPTs.
  if( !is_single() )
    return;

  $data = $_COOKIE[ $view_cookie ];

  if( !isset( $data ) {
    // If no cookie is set, set it to a count of 1 and to expire in 24 hours.
    setcookie( $views_cookie, 1, time() + $cookie_ttl );
  }
  else {
    $views = intval( $data );
    
    if( $views < $max_views ) {
      // If cookie is set and under threshold, increment it.
      setcookie( $views_cookie, ++$views, time() + $cookie_ttl );
    }
    else {
      // If cookie is at the threshold, redirect the visitor.
      wp_redirect( home_url( '/max-views-exceeded-page' ) );
    }
  }
}

add_action( 'init', 'wpse408666_handle_visitor_cookie' );

This implementation is very basic (and untested) and is intended just for illustration – it doesn’t use any tamper prevention, the expiration time for the cookie is set based on the server time when it will expire based on the client’s time.

Fingerprinting

Fingerprinting” is the practice of attempting to derive some notion of an end-user’s identity through a number of often inconspicuous details – if a certain user-agent accesses a site from a similar IP or geolocation during certain hours, it may well be the same person, for instance. It is difficult to pull off effectively, and generally requires a substantial amount of resources depending on the end-goal.

The industrial application of the practice primarily falls into the domain of advertising networks and the considerably more ethically-questionable data brokerage industry. Due to the cost, complexity, and possible ethical and legal implications, effective fingerprinting is rarely an appropriate solution.