Counting clicks on article links

Hi all,

I’m building a website where you see a list of external links (like hackernews). There are no single-link pages (like an article page) just a homepage with all the links.

Besides a featured image, title, subtitle, date, I also want to show that how many clicks received each link.

This is how my PHP looks like at the moment:

<div id="grid" data-columns>
      
      <?php foreach($page->children()->visible()->flip() as $article): ?>

        <div class="box">
          <a href="<?php echo $article->box_link() ?>" target="_blank" class="box-button">
            <img src="<?php echo $article->image()->url() ?>" alt="">
            
            <div class="contentText">
              <time datetime="<?php echo $article->date('c') ?>" pubdate="pubdate"><?php echo $article->date('Y.m.d.') ?></time>

              <p><?php echo $article->clicks() ?></p>

              <h3><?php echo $article->title() ?></h3>
              <p><?php echo $article->box_subtitle()->excerpt(300) ?></p>
            </div>
          </a>
        </div>

      <?php endforeach ?>

      
    </div>

So as you can see, I already put an $article->clicks() line, which will show the number of clicks from the content folder.

I tried to use the <?php $page->increment('clicks') ?> solution, but that added +1 count each time I refreshed the page.

Do you have any idea, how can I increase the value of the “Clicks” field based on clicks?

Thank you for your help!

You would have to use the increment function as a result of an Ajax call that is triggered on clicking a link.

I thought I should use the increment function. Since I’m not really familiar with Ajax call, can you please help me, how can I trigger the increment function with Ajax clicking a link?

Thank you very much!

As you already experienced, without any condition, the increment function is triggered every time you reload the page, which is not what you want, since you only want to increment the counter if a link is clicked. I’ll get back to you regarding the Ajax call later today.

If you are in a hurry and want to find out for yourself, check out the Ajax recipe in the cookbook.

I’m not in a hurry. I’m looking forward to your answer later today. Thanks:))

In your template, you can check if an Ajax request was made like this and then increment the likes:

<?php 
if(r::ajax()) {
  $page->increment('likes');
} 
?>

In your footer (jquery version)

<?php echo js('assets/js/jquery.js'); ?>
<script>

$(function(){

  $('.showcase-link').on('click', function(e) {
    var url   = $(this).attr('href');
    $.get(url);
  });

});
</script>

This is a very basic variant, you can, of course, add success and error handlers and what not.

Of course, you can also do this in vanilla JS, but since I’m not good at that…

Thank you for your help, but unfortunately it still don’t want to work…

This is how my modified code looks like at the moment:


<div id="grid" data-columns>
      
      <?php foreach($page->children()->visible()->flip() as $article): ?>

        <div class="box">
          <a href="<?php echo $article->box_link() ?>" target="_blank" class="box-button showcase-link">
            <img src="<?php echo $article->image()->url() ?>" alt="">
            
            <div class="contentText">
              <time datetime="<?php echo $article->date('c') ?>" pubdate="pubdate"><?php echo $article->date('Y.m.d.') ?></time>

              <?php 
                if(r::ajax()) {
                  $article->increment('clicks');
                } 
              ?>

              <p><?php echo $article->clicks() ?></p>

              <h3><?php echo $article->title() ?></h3>
              <p><?php echo $article->box_subtitle()->excerpt(300) ?></p>
            </div>
          </a>
        </div>

      <?php endforeach ?>

      
    </div>

And since, I already loaded in jQuery in my footer, I just added the following:

<script>
        $(function(){

          $('.showcase-link').on('click', function(e) {
            var url = $(this).attr('href');
            $.get(url);
          });

        });
    </script>

What am I missing here?

This code

<?php 
      if(r::ajax()) {
        $article->increment('clicks');
      } 
 ?>

should be in the template of the page that is called (i.e. probably the article.php template in your case).

Change $article to $page in the new location.

1 Like

You’re awesome! It works! But I have a small problem…

When a user clicks on my link, that doesn’t link to a page on my site, but it leads to an external page, like a Facebook post.

So, I tried your version, and if I set it to link to one of my page, your solution works, but my goal is to immediately direct the user to an external page.

So in my code block, the box_link() leads to an external (mostly Facebook post URL) set by the editor in the Kirby Panel, so I cannot put anything into the article.php because that doesn’t get loaded along the way. Do you have an idea how we can get around that?

But I feel we’re almost there! Thank you!!! :slight_smile: :slight_smile:

Hm, but in that case the linked post does not have a text file where the click can be incremented anyway? Where do you want to save that click?

They have a text file, that’s not a problem. The problem is that the user will never land on the article.php subpage.

Imagine like this:

I have a page with full of boxes (let’s call this page a blog page for convenience). The editor can add a new box to this blog page by creating a new subpage in the Kirby admin panel. So each of these boxes have their own folder with own .txt file in it.

Each box has a featured image, a title, a short description, a date and most importantly a custom URL. So when the user clicks on one of these boxes on the blog page, it will link to this custom url, which is outside of my webpage (it will be URLs of various Facebook posts) instead of loading in the article template. Next to the date I also want to add this click view number that we’re focusing on now.

So each box acts like a small article (have separate txt files) and looks like blog posts on a blog page, but when the user clicks on them, the user will end up on a Facebook page, rather than an article page on my website.

So this is why it won’t work putting code in the article.php file, because that won’t be loaded along the way. But I still have separate txt files available for storing specific click numbers for each and every box. :slight_smile:

Then you probably have to prevent the default link action in your Javascript, call a route that does the incrementing and on success redirect to the Facebook post.

Thank you very much! Now it’s working! :slight_smile:

You helped a lot to me, so thank you again! :slight_smile:

@danielkorpai: Would you post your full solution on this?

Thanks!

Out of interest: What would a solution to this look like for K3?
Thanks for any hints you can provide (cookbook would be awesome, too)!

The only difference is that there is no increment method anymore, so you would have to use $page->update()(which requires an authenticated user or the Almighty, i.e. $kirby->impersonate('kirby')).

And probably no jQuery…

Why no jQuery / JS? How to make the AJAX request?

If you use jQuery anyway, go ahead. But is has come out of fashion, it seems…

A post was split to a new topic: How to implement a download counter