*UPDATE[2019/01]: There's a new MODX Extra that is designed from the ground up to be more accurate and flexible—able to handle the "Most Popular Pages" use case plus a whole lot more. Check it out here.
Have you ever wanted to display a list of Most Popular pages or blog posts on your MODX CMS site? Searching through the MODX Extras repo didn't return any easy, viable solutions for me. So without a snippet to do the job, how can we deliver this (unspectacular but often requested) functionality?
HitsPage is a relatively unknown (only 300 downloads as of this writing) and oddball plugin written by Russian MODX developer Valentine Rasulov. The documentation is a bit sparse, and of course, mostly in Russian, so everything I know about this Extra I found out by experimenting ;)
What does HitsPage do? It counts page views. It's unrefined in doing so - it doesn't count unique visitors or any other metric besides the number of requests a given page has received. HOWEVER, it does one thing that makes it indispensable for our purposes - it outputs the hit counter results to a MODX Template Variable (or, TV). I'll go into why that's so great later on, but let's explore this snippet a bit more...
- You can install it via Package Management in MODX Revo versions 2.1.x or later. Earlier versions aren't supported. If you need to update, read my post on the MODX Advanced Install and Updating Advanced MODX Installations.
- There's no Official Documentation, and it seems the original blog post describing its usage in Russian has been removed.
- You can also download the package here: https://modx.com/extras/package/hitspage
Upon installation, HitsPage creates two TVs, but only one seems to be useful at this time. It is named "HitsPage".
- Assign the HitsPage TV to the Template(s) used by the pages you want to track views on.
- Add a placeholder for the output, like this:
You MUST put the placeholder on the page somewhere, whether it's in your Template or the Resource Content field. It seems to "activate" the page counter. If you don't want to display it on the web, just wrap it in a div styled display:none. That's it for the plugin implementation - easy, right?
Now, every time the page is viewed, the value is updated in both the TV HitsPage and the placeholder. If at any time you want to reset the counter on a given page, just set the value in the TV back to the default value of 1 - or whatever integer you want to start counting from.
At first I was thrown off by the fact that you don't actually call the TV tag
[[*HitsPage]] anywhere - doing so breaks the Plugin! The TV just sits there, holding the value. This rather odd behaviour is exactly what makes it viable as a Most Popular Plugin, with a little help, of course.
get Jiggy With getResources
getResources is hands down my favorite MODX Snippet of all time (see another tutorial here). If an evil villain was forcing me to make the demented choice of saving only one MODX Snippet from annihilation, getResources would be the one. It's written by Jason Coward of the MODX Core Team. You can collect, sort, and customize the display of MODX Resources in a nearly limitless number of ways.
Starting with getResources version 1.2.0, you can not only filter results by TVs, but sort them based on their values! Cue heavenly chorus and beam of sunlight through parting clouds - HitsPage dynamically stores page views in a TV, getResources filters and sorts by TVs. Presto!! A Most Popular Post Plugin for MODX!!
- Install via Package Management or download here: https://modx.com/extras/package/getresources
- Official Documentation - be sure to read this thoroughly to truly grasp how much is possible with getResources: https://docs.modx.com/extras/revo/getresources
The Snippet Call
[[!getResources? &parents=`[[*id]]` &limit=`3` &tpl=`myTpl` &heading=`h5` &sortbyTV=`HitsPage` &tvFilters=`HitsPage<<200` &sortbyTVType=`integer` ]]
Break it down:
[[!getResources?» Due to the fact that the HitsPage plugin saves TV values dynamically, we need to call getResources uncacheable because we want it to retrieve the most current value of those TVs in order to sort them. As we get more and more pages (and TVs) on the site, this will slow things down.
&parents» Targeting the children of the current document, on which the Snippet call resides.
&limit» Limit the output to three instances.
&tpl» As usual, the output is endlessly configurable. Any of the placeholders and resource fields available to getResources can be used here.
&heading» In "myTpl" I have a placeholder wrapping the page's title, like this:
<[[+heading]]>[[+pagetitle]]</[[+heading]]>This allows me to use the same "myTpl" on different areas of the site, while being able to change the type of HTML heading tag used. Setting the property in the Snippet call passes the desired value to the placeholder in the template chunk.
&sortbyTV» This is where the magic begins. We're using the HitsPage TV to sort our results. By default, the "sortdirTV" property is set to "DESC" which means the pages with the most hits will show up first on the list. Perfect!
&tvFilters» Here we're filtering the results to only those documents that have a HitsPage TV value of less than 200. I did this so that if a page gets too popular, it drops off the list, letting other, less popular pages get the spotlight. You can configure this however you want or skip it altogether.
HitsPage>>200` for example will set a minimum popularity threshold of 200 hits.
&sortbyTVType» To be honest, I threw this in for good measure - I don't know if it's strictly necessary.
As you can see, the world's your oyster when it comes to collecting and sorting documents in MODX. Jason Coward has granted us access to any custom TVs as well, meaning you literally can make up anything, attach it to any document, and then sort on it. The hidden gem of a plugin, HitsPage, sets the TV value for us based on pageviews, and that's all we need to make ourselves a Popular Posts Plugin - even in the absence of an "official" one. That's MODX: MODular and eXtendable ;)
*UPDATE: HitPage has gone through a LOT of changes since I wrote this, and I just helped a client implement this so I thought it'd be helpful to other folks if I documented the changes here:
- Instead of putting the
[[!+hitss]]placeholder on the page to activate the plugin, you call the Snippet
[[!HitsPage? &saveTv=`true`]]. There a new property you must set,
true` in order to increment the value in the TV like you need to for this Most Popular implementation.
- The package no longer creates any TVs for you. You must create a TV called "HitsPage" for this Most Popular implementation with getResources TV filtering. If you're using
integer` you may as well set the input type on the TV to "Number", although neither of these is strictly necessary.
- The package includes the Plugin "HitsPage" and the Snippet "HitsPage". With this method of calling the Snippet, you can actually deactivate the Plugin, as it shouldn't need to do anything. Unless you're using a different implementation of HitsPage elsewhere on the site.
- Last but not least, there's a new version of getResources coming out that vastly improves performance when querying the TV table(s) so when that comes out, make sure you update getResources :)
*IMPORTANT UPDATE: There's a more performant way to do this now, using the Hits Snippet.