Jump to content
David Karich

Page Hit Counter – Simple Page View Tracking

Recommended Posts

22 hours ago, loukote said:

Above you mention the ProCache module. Do I understand correctly that the counting will work correctly even with the standard PW template cache mechanism?

Hi @loukote, yes that's right. The tracking and counting of PageViews also works with any form of cache. Because a small Javascript is injected, which tracks the view asnychronously, past the cache, without affecting the cache.

Share this post


Link to post
Share on other sites

Haven't tested yet, but it seems that it stores only int value of total sum of all time views? So not possible to use for "most viewed pages this week" for example?

Other than that it looks like a perfect module for many use cases!

Share this post


Link to post
Share on other sites
12 minutes ago, apeisa said:

Haven't tested yet, but it seems that it stores only int value of total sum of all time views? So not possible to use for "most viewed pages this week" for example?

Other than that it looks like a perfect module for many use cases!

Hello apeisa, 

that's correct. It totals all views. However, you can still display something similar to a function like "most of the week". If the page being tracked has a date field. For example I have a news template with the date field "start_date" and activated tracking. Now you can output the 5 most read news of the last week with the following selector: 

$startDate = strtotime("-1 week");
$endDate = strtotime("now");
$bestNews = $pages->find("template=news, start_date>={$startDate}, start_date<={$endDate}, sort=-phits, start=0, limit=5");

 

  • Like 2

Share this post


Link to post
Share on other sites

Yep, that would do in many cases - if you want to promote fresh articles!

Share this post


Link to post
Share on other sites

Just spotted a curiosity in my Jumplinks 404 log...

1512599478_2019-03-1402_33_20.thumb.png.01ebc07a890568a285b5fa060cf43ca8.png

.. and found out it's from here PageHitCounter.min.js.

"use strict";(window.PHC=window.PHC||{}).t=function(){try{var e=document.getElementsByTagName("BODY")[0],t=parseInt(e.getAttribute("data-phc"));if(!isNaN(t)){var n=new XMLHttpRequest;n.open("POST",location.pathname.replace(/\/?$/,'/')+"phcv1",!0),n.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send(encodeURI("pid="+t))}}catch(e){}},PHC.t();

 

Did I missed that before or is this not working as intended?

2019-03-14 02_32_58.png

Share this post


Link to post
Share on other sites

Found another thing... 

My 404 page has the same template as most of my other pages as it's kind of a page builder.

Trying to reset the page count for that template the 404 page still has it counts while other's dont.

400061712_2019-03-1403_44_51.png.8f4ffc773407fd7939eef86494b002b4.png

Trying to be clever and looking up the ID of that page (27) in order to reset the view count an error message shows up.

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') AND `data` > 0' at line 1

404599281_2019-03-1403_49_00.png.87a346fef9a3a8f524e7953d4a9101e7.png

Share this post


Link to post
Share on other sites

Hey @David Karich , just passing by to say that I've sent two small PRs for correcting some typos. Super minor thing, but hope you like it. 🙂

I'm planning to adapt your code to build another module, a download counter. My use case is where the file is hosted on another server, and its link is managed through a URL field.

Share this post


Link to post
Share on other sites

PageHitCounter Version 1.2.4

Thanks to @wbmnfktr for reporting the issues. And thanks to @Sergio for the corrections. Both issues have been fixed in version 1.2.4 and the corrections have been applied. Changelog as always updated in the first post. Explanations of the bugs below.

On 3/14/2019 at 2:51 AM, wbmnfktr said:

Just spotted a curiosity in my Jumplinks 404 log...

1512599478_2019-03-1402_33_20.thumb.png.01ebc07a890568a285b5fa060cf43ca8.png

.. and found out it's from here PageHitCounter.min.js.


"use strict";(window.PHC=window.PHC||{}).t=function(){try{var e=document.getElementsByTagName("BODY")[0],t=parseInt(e.getAttribute("data-phc"));if(!isNaN(t)){var n=new XMLHttpRequest;n.open("POST",location.pathname.replace(/\/?$/,'/')+"phcv1",!0),n.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send(encodeURI("pid="+t))}}catch(e){}},PHC.t();

 

Did I missed that before or is this not working as intended?

2019-03-14 02_32_58.png

The functionality has always been and is correct. The module sends the data to a fictitious endpoint of the current page. Then the module hooked in before a 404 is triggered and writes the data. The problem here was that the module "Jumplinks" had a lower priority than PageHitCounter. Therefore the request was logged as 404, because jumplinks were executed earlier. Now fixed, PageHits are not logged as 404, regular 404s will be. 

On 3/14/2019 at 3:49 AM, wbmnfktr said:

Found another thing... 

My 404 page has the same template as most of my other pages as it's kind of a page builder.

Trying to reset the page count for that template the 404 page still has it counts while other's dont.

400061712_2019-03-1403_44_51.png.8f4ffc773407fd7939eef86494b002b4.png

Trying to be clever and looking up the ID of that page (27) in order to reset the view count an error message shows up.


SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') AND `data` > 0' at line 1

404599281_2019-03-1403_49_00.png.87a346fef9a3a8f524e7953d4a9101e7.png

Here was the problem that system templates or pages are excluded in the normal search, without the selector "include=all". This is now included by default.

On 4/10/2019 at 1:11 AM, Sergio said:

Hey @David Karich , just passing by to say that I've sent two small PRs for correcting some typos. Super minor thing, but hope you like it. 🙂

I'm planning to adapt your code to build another module, a download counter. My use case is where the file is hosted on another server, and its link is managed through a URL field.

Oh, my gosh, there were a lot of typos in there. So if you have a lot on your mind what you're going to code next, you don't look at the comments. Anyway, many thanks for the corrections!

And by the way, I'd love to. Take the code and build something new out of it! 🙂 

  • Like 5

Share this post


Link to post
Share on other sites

It doens't work if you have have "Allow URL Segments" option enabled on the template, at least not in my case. Can this be fixed?

Share this post


Link to post
Share on other sites
9 minutes ago, lokomotivan said:

It doens't work if you have have "Allow URL Segments" option enabled on the template, at least not in my case. Can this be fixed?

Right, I haven't tested it yet. Can you send me your sample configuration? Or did you just activate the option without defining segments?

Share this post


Link to post
Share on other sites
13 minutes ago, David Karich said:

Right, I haven't tested it yet. Can you send me your sample configuration? Or did you just activate the option without defining segments?

No segments defined, "just Allow URL Segments?" option checked. When i uncheck it, it start counting 🙂 

Edit: Otherwise works great, thank you for this module 🙂

  • Like 1

Share this post


Link to post
Share on other sites

Okay, thanks for the report. I'll take a look next week. Probably going to be hard to combine.

Share this post


Link to post
Share on other sites
On 4/18/2019 at 10:21 AM, lokomotivan said:

It doens't work if you have have "Allow URL Segments" option enabled on the template, at least not in my case. Can this be fixed?

David, I checked here on my project. The module does increment the counter for a page that has Segments turned on BUT it doesn't increment the counter when you access "page-url/segment", which would be expected, right? 

Share this post


Link to post
Share on other sites
11 hours ago, Sergio said:

David, I checked here on my project. The module does increment the counter for a page that has Segments turned on BUT it doesn't increment the counter when you access "page-url/segment", which would be expected, right? 

Yep, i think that should be expected. In my case there was no segment in the url just option enabled. Ill test it again, maybe i missed something.

Share this post


Link to post
Share on other sites

Sure, but I should rephrase that, it should increment the counter for the page when accessing one, or more, of its segments. Considering the visitor is a different user or that the cookie expired, of course.

Share this post


Link to post
Share on other sites

@lokomotivan @Sergio I have now experimented with many options to solve this problem. However, there is only one way, which covers both behaviors. If you don't want segments to be counted, just enable the option as the behavior is current. But if segments are to be counted as well, the segments MUST be defined in the template configuration. For dynamic segments with RegEx. For this I have inserted a passage in the readme with the link to the PW help. 

There is currently no other option. The problem is that the Page Hit Counter hooked into the PageNotFound process (But I also tried PageRender, etc.). If URL segments are allowed but not defined, a 404 is never triggered from Processwire. This means that the Page Hit Counter cannot be called. For the tracking of segments, so simply define the segments. 🙂 

I also released an update with version 1.2.5, which improves the behavior when tracking 404 errors. All infos and download as always in the first post.

  • Like 3

Share this post


Link to post
Share on other sites

@David Karich Very useful module, works like a charm!

I was just wondering if there could be a way to call the resetPageViews from a template file? I would find it more valuable if there's an option to reset templates' page hit counter from the template itself. That way, we don't have to give access to the module settings for the average user to reset page hits.

I've tried to use it, but it seems that the module itself doesn't have a clue about the modules' methods. If this is something that Processwire doesn't process, someone could point out that for me :D

Thank you!

 

Share this post


Link to post
Share on other sites

@David Karich Thanks again for the module. 

What do you think about adding an option to manually load js scripts from a custom folder?

Share this post


Link to post
Share on other sites

A very nice simple tracker - thank you David.

I have one issue – just realized, that pages with tracking activated are "edited" by each hit by "guest" (field phits) – that's obvious. In combination with the module "changelog" – where I want to list pages last edited only by editors – the "edited by guest" makes it difficult to filter out what my editor colleagues have changed recently.

Maybe it's worth adding an option to set the field->save method to "quiet"? 

Quote

quiet (boolean): Specify true to bypass updating of modified user and time

https://processwire.com/api/ref/pages/save-field/

 

Edited by sz-ligatur
too fast… I realized that the plugin save hits via db direct access… so I rashly jump to the wrong conclusion I guess…

Share this post


Link to post
Share on other sites

Does the info section under the settings tab say the same?

Just wondering as I looked into one of my projects and those page modification dates are unchanged.

Share this post


Link to post
Share on other sites

It was my mistake – I use a download-file template, that forces downloading a pdf. To track this I used $page->save('phits') to update the counter. Obviously this is a page edit… by guest.

if ( $user->isGuest() ) {

		$page->phits += 1;
        $page->of(false);
		//$page->save('phits');
		$page->save('phits', array('quiet' => true));
		$page->of(true);
    }

The added option 'quiet' does the trick… 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Sanyaissues
      I hadn't developed a website for a while, but here we are. It's a very simple minimalist website to showcase the latest work of Dominican Artist Patricia Abreu Mota.
      Site: https://patriabreu.com
      Modules:
      Procache ❤️ Seo Maestro Profiler Pro Lister Pro ProcessRedirects
    • By benbyf
      Hi, Looking to create form elements on a page–some input with a colection of form inputs and the appropriate labels and variables for that input. I've used ProForms in the past and rolled out my own when creating simply one off forms, but I wonder if anyone has found a good way of allowing form creation on page editing so that clients can adhocly make and edit forms?
      Thanks
    • By verdeandrea
      Hello,
      I am using ProCache v3.1.8 on ProcessWire 3.0.96.
      Everything worked fine in the past, but today I noticed that the css file serverd by procache gives a 410 error. 
      The file is there, I checked.
      I deleted the cached files, I deleted the css file, I looked into the .htaccess file looking for some clues about this problem but nothing worked.
      The only way i can see my website correctly again is disabling ProCache. 
      Has anyone any clue on what could be the cause of the problem or on what should I do to fix it?
      Thanks!
    • By Atlasfreeman
      Hi!
      I want to make a small site, a one page site.
      And i have this idea about doing 2 to 3 diffrent template that i can load into the index / home page.

      I want to do this with an array so that i can keep creating more topics (with the template) id needed.
      <?php include('./head.inc'); // include header markup ?> <?php $children = $page->get('template=onecolmn|twocolumn, sort=sort'); foreach($children as $child) { include($child); } ?> <?php include('./foot.inc'); // include footer markup ?>  
      As you can see i have to template wish i want to control from the backend.
      I know include does not work this way, put what is my other option to make an array that loads the whole page on an other pages.
       
       
    • By Liam88
      Hi All,
      New user over at Processwire and have been rebuilding my site based on this CMS.
      I have been able to find so many answers through Google but I'm a little stuck on this one.
      I have my services page -> services categories -> category children.
      An example of those would be - domain -> services -> ppc -> management
      I also have a set of tags which have different names - services-tag -> grow-your-traffic
      Under these tags I would have multiple links to pages such as ppc, seo, social media and so on.
      A second example would be - services-tag -> convert-your-traffic
      Under here i would have multiple links to pages such as CRO
      Now the set of tags are not visible on-site as they are only created to give overview content to the main services categories.
      Using the categories and the tags I am looking to produce a layout such as (i have also attached an image as an example:
      Tag_1 headline
      Pull all services categories linking to Tag_1
      Tag_1 snippet
      Tag_2 headline
      Pull all services categories linking to Tag_2
      Tag_2 snippet
      So far I have this snippet which is pulling in the tag content but unable to get the posts to show under each of the tags. 
      If i change the if and statement to "tags" instead of "tag" then all posts show under all tags. Where as i want it to show only the posts which are linked to that tag.
      <?php namespace ProcessWire; $tags = $pages->get("/categories-services/")->children(); // Gets the tags $posts = $pages->get("/services/")->children(); // Gets the services categories $link = $tags->ref_6; // Gets the tags and services categories link - under here you have pages_id (services cat id) and data (tags id) // Tag header and summary foreach($tags as $tag) { // This breaks down the tags into sections echo '<section id="services"> <div class="container"> <div class="row"> <h2 class="heading-1"><span>'. $tag->headline.'</span></h2> <p class="mb-5">'. $tag->summary.'</p> </div> <div class="row justify-content-around services">'; // Main services categories that link to the above tags if ($posts->id === $link->pages_id && $tag->id === $link->data){ foreach($posts as $service){ // This pulls in the services categories under the tag header. echo '<div class="card flex-card" id=""> <div class="card-img"> <a href="/'. $service->name.'" title="'. $service->name .'"> <img class="card-img-top" src="../assets/files/'. $service->id.'/'. $service->img_1.'" alt="'. $service->img_1.'" title="'. $service->img_1.'"></a> </div> <div class="card-body"> <h3 class="card-title">'. $service->headline.'</h3> <p class="card-text">'. $service->summary .'</p> <div class="card-action"> <a href="" title="'. $service->name .'" role="link" class="link">View service<span></span></a> </div> </div> </div> '; } } // Grey snippet text echo '</div> </div> </section> <div class="snip-2 light-grey"> <div class="container"> <div class="row text-center">'. $tag->get('grey') .'</div> </div> </div>'; } ?> I appreciate this is a long post but i'm trying to be clear as I appreciate everyone's time.
      Any insight into where I am going wrong is greatly appreciated.
      Liam



×
×
  • Create New...