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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • 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



    • By Harmen
      I want to add a few pages to an AsmSelect Page field inside a repeater using the following code:
      $trialsPage = wire("pages")->get(28422); // Get the page $trialsPage->of(false); $newTrial = $ordersPage->trial_repeater_orders->getNewItem(); // Add item to repeater foreach ($selectedProducts as $selectedProduct){ $productPage = $pages->get("template=product, reference=$selectedProduct"); $newTrial->trial_selected_products->add($productPage); } $newTrial->save(); $trialsPage->save(); However, when I check the page where the field is located it doesn't have the new values as expected. The selected pages exist, the field is in the right location, made sure that the output formatting is turned off: $page->of(false); But it still doesn't work with a variable. No matter what I try, it doesn't work.
      It only works when I replace $selectedProduct with a hardcoded string. Am I doing something wrong here?
    • By louisstephens
      So I have a form, once completed, will create new pages. All in all, this is eazy-peezy for me now. I guess I need a bit of guidance on how to actually structure the rest of my code.  I thought I could just write a function (_func.php) and pass the fields to the function and let it do its' thing. However, I am kinda hitting a road block when I do it this way. 
      I currently am passing first name, last name, city, state (options field), and making pages based on the first/last names. I guess where I run into some issues is I am trying to check to see if the "page" already exists, and if it does, throw out an error:
      In the home template:
      if(isset( $_POST['submit'])) { $firstName =Trim (stripslashes($_POST['firstname'])); $lastName = Trim(stripslashes($_POST['lastname'])); $fullName = $firstName . $lastName; $city = Trim(stripslashes($_POST['city'])); $state = Trim(stripslashes($_POST['state'])); $lowerCaseName = strtolower($fullName); $people = $pages->find("template=person"); foreach ($people as $person) { $checkFirstName = $person->first_name; $checkLastName = $person->last_name; $checkFullName = $checkFirstName . $checkLastName; if ($checkFullName === $lowerCaseName) { echo "<p>" . "This person has already created a page. Please choose a different name." . "</p>"; } else { echo "hey"; processNewPerson(need_to_pass_person_details_to_function); } } // end foreach In _func.php:
      function processNewPerson($list) { $u = new Page(); $u->template = "person"; $u->parent = wire('pages')->get("/people/"); $u->title = ; $u->first_name = ; $u->last_name = ; $u->state = ; $u->city = ; $u->save(); $u->setOutputFormatting(false); } I am a little unsure of how to actually pass all the information to the template, as well as if this is even the best approach to do this. Would it make more sense to do this in a class, or keep it the way it is?
    • By quickjeff
      Hi Guys, I have seen some other threads that talk about this but nothing recent nor in line with what I need. 
       
      I have basically created a page in which I am tracking the number of views. I update the counter which is tied to a field I added to the page's template that I am tracking. The field is hidden from the website admin and only used for this data. 
       
      However, now I need to track it on a daily basis. I am thinking of keeping track of all time view total for 30 days and perhaps saving that and allowing the user to see the page views of last 7 days, each day as a number and then 30 days of data. This way if I want to build in reporting functionality I can. 
       
      What I need help with adding a date to the page_views field but also, knowing how many page_views for today, yesterday, day before etc. 
      Here is what I have so far and its working. Now I need to associate a date with every day. NOT every update of the page_views field. 
      if (!$user->hasRole('superuser')) { $page->page_views += 1; $page->of(false); $page->save('page_views'); $page->of(true); } echo $page->page_views; Any guidance, help, suggestions is absolutely appreciated. 
      Thanks!!!!
    • By quickjeff
      Hi Guys,
      Right now, I am using parents as breadcrumbs but I have pages under a parent page just to keep things organized. The pages are called in other areas of the site. 
      I am trying to create user path history breadcrumbs.
      Meaning: If the user clicked a link to the page, it will show the path he took. Has anyone done this? Would love to see who has before I dive in.
      Thanks. 
×
×
  • Create New...