Jump to content
j00st

Cross-referencing tag used in Pages

Recommended Posts

Hi Everyone!

Wondering if the community can help me out on the following issue I'm struggling with;

I'm using a Page titled Tags, with children Pages for separate Tags (a Tag, maybe obvious, but still...) 
These tags are being used as...tags! From a dropdown on the article-page in the CMS. Works like a charm. But...

I actually want to use these tags as cross-reference as well. Basically I want to make a page with all tags on it,
and for each tag have a list with all the Pages it's connected to (and preferably even pull content from those pages).
Might be I overlooked a previous post on this subject, or that there's a Module for these kind of things,
but since I couldn't find anything so far, I thought I'd try my luck here! 

Ideas, options, solutions, suggestions...all welcome!
Thanks!

Share this post


Link to post
Share on other sites

@j00st, you might like to take a look at the Connect Page Fields module:

Once the module is installed it takes care of keeping the fields in sync but if you already have your articles(?) tagged you would write some API code for a one-time operation to iterate over your article pages and add them to the selected tag pages.

  • Like 1

Share this post


Link to post
Share on other sites

Hi Sérgio and Robin, thanks for your quick replies!

@Sérgio; yes, that would be the result, with the tag clickable to show the connected articles. Is this something you're familiar with in setting it up? And with my suggestion to showing the related articles would you refer to Robin's plugin?

@Robin S; Ah good, I'll definitely have a look at the module! Just read through the page quickly, and the basis of it would be for me to link a Pagefield 'articles' on each Tag page, and on the Article use the existing Pagefield Tags, correct?
And to perhaps complicate it; If I also want to connect the authors of articles to a tag, this would be another connected field pair right?
 

Share this post


Link to post
Share on other sites
1 hour ago, j00st said:

@Robin S; Ah good, I'll definitely have a look at the module! Just read through the page quickly, and the basis of it would be for me to link a Pagefield 'articles' on each Tag page, and on the Article use the existing Pagefield Tags, correct?
And to perhaps complicate it; If I also want to connect the authors of articles to a tag, this would be another connected field pair right?

Yes, correct on both.

One advantage of the Connect Page Fields module is that it can make the generation of your tags page more efficient. How much so depends on what you want to show on the tags page. To explain...

For a page like the screenshot from @Sérgio, with a count next to each tag link, the typical way using only common API methods would be something like:

$tags = $pages->find("template=tag, sort=title");
foreach($tags as $tag) {
    $count = $pages->count("tags=$tag"); // count how many pages have this tag selected
    // now output the tag link and count
}

And if you happened to want to list the articles that use each tag underneath that tag you would do something like:

$tags = $pages->find("template=tag, sort=title");
foreach($tags as $tag) {
    $tagged_pages = $pages->find("tags=$tag"); // find pages that have this tag selected
    // now output the tag and the list of pages
}

A $pages->count() has less overhead than a $pages->find(), but it's still a lot of DB queries if you have a lot of tags. You'd probably want to cache this if you did it this way.

With Connect Page Fields, the pages that use the tag are stored in a Page field so you can easily get a count or the pages themselves directly:

$tags = $pages->find("template=tag, sort=title");
foreach($tags as $tag) {
    // you probably wouldn't bother assigning these to variables but just for demonstration
    $count = $tag->articles->count();
    $tagged_pages = $tag->articles;
    // output your tag, count, etc
}

And for one more option involving a single SQL query on the tags table see this:

 

  • Like 3

Share this post


Link to post
Share on other sites

@Robin S's code is an excellent approach, @j00st! The ConnectPageFields module is great to have the admin user manage the relations is a much easier way. I have to implement it on this site the screenshot came from yet, as when I developed these connections the module wasn't available. :)

As for your question, the code I used to create this page shown on the screenshot is taken from Ryan's blog profile tag template, mine version is below:


/**
 * Generate a list of tags A-Z
 *
 * Used by the /site/templats/tags.php template file.
 *
 * VARIABLES:
 * ==========
 * $tags PageArray of tags
 *
 * Each of the tags has a numPosts property containing the number of posts used by the tag.
 *
 */

$lastLetter = '';
$out = '';
$letters = array();
$tags = $page->children();

foreach($tags as $tag) {
  $letter = strtoupper(
    substr(
      $sanitizer->pageName($tag->title, true)
    , 0, 1
    )
  );

  if($letter != $lastLetter) {
    if($lastLetter) $out .= "</ul></div>";
    $out .= "<div class='letter-group'>";
    $out .= "<h3 id='letter_$letter' class='bg-tags text-center'>$letter</h3>";
    $out .= "<ul class='no-bullet'>";
    $letters[] = $letter;
  }
  $lastLetter = $letter;

  $page_count = $pages->count("tags=$tag");
  $class = $page_count >= 10 ? 'u-strong' : '';

  if($page_count > 1) {
    $out .= "<li class={$class}><a href='{$tag->url}'>{$tag->title} <span class='color-tags-dark25'>({$page_count})</span></a></li>";
  }

}
$out .= "</ul></div>";
/I'm using TemplateLatteReplace module to outup to a view file.
$view->letters = $letters; 
$view->tag_list = $out;

 

  • Like 3

Share this post


Link to post
Share on other sites

Wow! Thanks for all the examples @Sérgio & @Robin S!
I'm going to run through them again, and see how I can best put them to use!
If this won't work, I don't know what will :) Thanks again!

  • Like 1

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 Robin S
      Displays image tags overlaid on the thumbnail using customisable colours. This makes it easier to see which images have which tags without needing to open the edit pane for individual images or changing to the list view.
      Screenshot

      Usage
      Enable tags for one or more image fields. Install the Image Thumbnail Tags module. Optionally configure colours for any of your tags.
       
      https://github.com/Toutouwai/ImageThumbnailTags
      https://modules.processwire.com/modules/image-thumbnail-tags/
    • By Andi
      Continuing my journey into PW hooks, I'm trying to find a way to retrieve all images from a page that explicitly *do not* have a certain tag (or tags) attached to them.
      Found this post from 2015
      But I'm wondering if there's a more elegant way to go about this.
      Let's say I have a multi-image field called "images_header" and instead of
      $page->images_header->findTag('mytag'); I would like to do this:
      $page->images_header->excludeTag('mytag'); So I'd be able to do
      // find images that don't have the tag "mytag" $images = $page->images_header->excludeTag('mytag'); // check if there's any images if (count($images)>0) { // do something.. } Would this be possible by hooking into Pagefiles somehow?
      There's this bit in /wire/core/Pagefiles.php Line 626 that I'd basically just need to reverse (or at least in my mind 😄 )
      public function findTag($tag) { $items = $this->makeNew(); foreach($this as $pagefile) { if($pagefile->hasTag($tag)) $items->add($pagefile); } return $items; } Any ideas on how this could be done in a graceful manner?
      Thanks in advance!
    • 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 David Karich
      The Page Hit Counter module for ProcessWire implements a simple page view counter in backend. Page views of visitors are automatically tracked on defined templates, with monitoring of multiple page views. This gives you a quick overview of how many visitors have read a news or a blog post, for example, without first having to open complex tools such as Google Analytics. This module quickly provides simple information, e.g. for editors. Or, for example, to sort certain news by most page views. For example for "Trending Topics".

       
      Works with ProCache and AdBlockers. With a lightweight tracking code of only ~320 bytes (gzipped). And no code changes necessary! In addition GDPR compliant, since no personal data or IP addresses are stored. Only session cookies are stored without information. 
      In addition, there are some options, for example filtering IP addresses (for CronJobs) and filtering bots, spiders and crawlers. You can also configure the lifetime of the session cookies. Repeated page views are not counted during this period. It is also possible to exclude certain roles from tracking. For example, logged in editors who work on a page are not counted as page views.

      Sort by hits and access page views (hit value)
      Each trackable template has an additional field called phits. For example, you want to output all news sorted by the number of page views.
      // It is assumed that the template, e.g. with the name "news", has been configured for tracking. $news = $pages->find("template=news, sort=-phits"); To output the page views of a tracked page, use:
      echo $page->phits; Example: Reset counter per API
      $modules->get("PageHitCounter")->resetPageViews("template=whatever", false); Example: Tracking a page hit via API and jQuery
      If you want to track a template that does not represent a full page to automatically inject a tracking script, you can define allowed API templates in the module that you can track. Below is an example of how you can track a click on news tag using jQuery. This will allow you to find out which keywords are clicked the most. For example, you can sort and display a tag cloud by the number of hits. Suppose your keywords have the template "news_tag". The template "news_tag" was also configured in the Page Hit Counter Module as a trackable API template.
      Example PHP output of keywords / tags:
      // Required: the data attribute "data-pid" with the ID of the template to be tracked. echo $pages->find("template=news_tag, sort=-phits")->each("<a href='{url}' class='news_tag' data-pid='{id}'>{title}</a>"); Example Tracking Script with jQuery:
      /** * Required: Data attribute "data-pid" with the ID of the news tag template * Required: Send the POST request to the URL "location.pathname.replace(/\/?$/, '/') + 'phcv1'" * Required: The POST parameter "pid" with the ID of the template */ $(function(){ if($('a.news_tag').length > 0) { $('a.news_tag').each(function(){ var tPID = $(this).data("pid"); if(tPID) { $(this).on("click", function(){ $.post(location.pathname.replace(/\/?$/, '/') + 'phcv1', {pid: tPID}); }); } }); } }); So simply every click on a tag is counted. Including all checks as for automatic tracking. Like Bot Filtering, Session Lifetime, etc.
      Notice: Tracking with URL segments
      If the option "Allow URL Segments" is activated on a template, the hits are only counted if the base URL of the page is called. If you want the hit to be counted even when a segment is requested, you MUST configure the segments in the template configuration. How to do this can be found here. If you use dynamic segments, configure them as RegEx. There is currently no other option. The problem is that the Page Hit Counter hooked into the PageNotFound process. If URL segments are allowed but not defined, a 404 is never triggered. This means that the Page Hit Counter cannot be called.
      _______________________________________________________
      Background: This module is the result of a customer requirement, where the editors are overwhelmed with analytics or no tracking tools were allowed to be used. However, a way had to be found to at least count page views in a simple form for evaluations. Furthermore, by using ProCache, a way had to be found to count views of a page without clearing the cache.
      _______________________________________________________
      Pros
      Automatic Page View Tracking Lightweight tracking code, only ~320 bytes (gzipped) No code or frontend changes necessary Works with ProCache! Even if no PHP is executed on the cached page, the tracking works Works with browser AdBlockers No cache triggers (for example, ProCache) are triggered. The cache remains persistent GDPR compliant, session-based cookie only, no personal information Filtering of IPs and bots possible Exclude certain roles from tracking Ability to reset Page Views Works with all admin themes Counter database is created as write-optimized InnoDB API to track events for templates that are not viewable No dependencies on libraries, pure VanillaJS (Automatic tracking script) Works in all modern browsers Pages are sortable by hits Cons
      Only for ProcessWire version 3.0.80 or higher (Requires wireCount()) Only for PHP version 5.6.x or higher No support for Internet Explorer <= version 9 (Because of XMLHttpRequest()) No historical data, just simple summation (Because of GDPR) Segment URLs can only be counted if the segments are defined Planned Features / ToDos
      API access to hit values Since version 1.2.1 Possibility to sort the pages by hits (Request by @Zeka) Since version 1.2.0 Don't track logged in users with certain roles (Request by @wbmnfktr) Since version 1.1.0 Possibility to reset the counter for certain pages or templates (Request by @wbmnfktr) Since version 1.1.0 Better bot filter Since version 1.1.0 Disable session lifetime, don't store cookies to track every page view (Request by @matjazp) Since version 1.2.1 Option to hide the counter in the page tree (Request by @matjazp) Since version 1.2.1 Option to hide the counter in the page tree on certain templates Since version 1.2.1 API to track events for templates that are not viewable Since version 1.2.2 Changelog
      1.2.6
      Bug-Fix: Set the counter of a cloned page to 0 Enhancement: The function for resetting counters is now available in the module as a public function to reset counters via own scripts on the API side (Request by @VeiJari) Enhancement: Documentation improvement API reset 1.2.5
      Bug-Fix: When counting 404 hits, cookies are no longer set. The session lifetime is deactivated for the 404 page Enhancement: Documentation improvement regarding URL segments 1.2.4
      Bug-Fix: Resetting the counters on system pages (e.g. 404) does not work (Reported by wbmnfktr) Bug-Fix: Tracking endpoint is logged as 404 if module "Jumplinks" is installed (Reported by wbmnfktr) Enhancement: Corrected few typos (Merged from Sergio #6 – THX!) 1.2.3
      Bug-Fix: Tracking script triggers 404 if pages are configured without slash (#3) Reported by @maxf5 Enhancement: Reduction of the tracking script size if it's gzipped (~320 bytes) Enhancement: Documentation improvement Enhancement: Corrected few typos 1.2.2
      New feature: API to track events for templates that are not viewable Enhancement: Documentation improvement 1.2.1
      API access to hit values Use $page->phits Bug-Fix: No tracking on welcomepage (Reported by wbmnfktr; Thx to matjazp) Bug-Fix: Tracking script path on subfolders (Reported by matjazp) Bug-Fix: Tracking on pages with status "hidden" Enhancement: Change database engine to InnoDB for phits field Enhancement: Option to disable session lifetime set session lifetime to 0, no cookies Enhancement: Better installation check Enhancement: AJAX Request asyncron Enhancement: Reduction of the tracking script size by ~20% Enhancement: Option to hide the counter in the page tree You can output the counter with the field name "phits" Enhancement: Option to hide the counter in the page tree on certain templates Enhancement: Option for activate general IP validation Enhancement: Reduction of tracking overhead up to ~30ms Enhancement: Better bot list for detection 1.2.0
      New feature: Sort pages by hits – New field phits Migrate old counter data to new field 1.1.0
      New feature: Exclude tracking of certain roles New feature: Reset Page Views Better bot filter and detection 1.0.0
      Initial release Notes
      By default, the page views are stored as INT in the database. This allows a maximum counter value of 4.2 billion views (4,294,967,295) per page. If you need more, change the type to BIGINT directly in the database. But I recommend to use Google Analytics or similar tools if you have such a large number of users.
      _______________________________________________________
      Download GitHub: ProcessWire Page Hit Counter (Version 1.2.6)
      PW Module Directory: ProcessWire Page Hit Counter (Version 1.2.6)
      Install via ProcessWire (Classname): PageHitCounter
      _______________________________________________________
      Update information
      If you have used version 1.2.1 from the DEV branch, please replace it completely with the new master version.
    • 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.
       
       
×
×
  • Create New...