Leftfield Posted May 15 Share Posted May 15 (edited) Hi @All, I made the page with only admin access so I can check in frontend visually (a chart) and links - what pages are most linked from blog pages and where I forgot to use this opportunity. This is important for SEO and removes manual labor. If you have any suggestions, feel free to shoot. Simple explanation: I got template=post and want to see stats with inner links to the homepage and service pages. Thanks @poljpocketfor helping me out! <?php namespace ProcessWire; // Calculate Internal Link Counts and Linked Pages $pages = wire('pages'); // Get all relevant pages directly in one query $relevantPages = $pages->find("template=post|service|home"); $blogPosts = $relevantPages->find("template=post"); $mainPages = $relevantPages->find("template=home|service"); // Function to check if a post DOES NOT link to ANY PUBLISHED service OR home page /** @var PageArray $mainPagesLinks */ $mainPagesLinks = $wire->wire(new PageArray()); foreach ($mainPages as $mainPage) { // this will remove duplicates by default $mainPagesLinks->append($mainPage->links("template=post")); } // Calculate Internal Link Counts and Linked Pages $linkCounts = []; $linkedPages = []; foreach ($relevantPages as $page) { $linkCounts[$page->id] = 0; $linkedPages[$page->id] = []; if ($page) { $items = $page->links(); if ($items->count()) { foreach ($items as $item) { if ($item->template != 'admin') { $linkCounts[$page->id]++; $linkedPages[$page->id][] = $item; } } } } } arsort($linkCounts); // Prepare data for the circle chart $chartLabels = []; $chartValues = []; foreach ($linkCounts as $pageId => $count) { if ($count > 0) { $page = $pages->get($pageId); $chartLabels[] = $page->title; $chartValues[] = $count; } } ?> <div class="container py-5 mb-5 links"> <div class="row py-5"> <div class="col-12 col-md-4 offset-md-4 pb-5"> <canvas id="linkCountChart" width="200" height="200"></canvas> </div> <div class="col-12 col-md-8 offset-md-2"> <div class="accordion" id="internalLinksAccordion"> <?php foreach ($linkCounts as $pageId => $count): ?> <?php if ($count > 0): ?> <?php $page = $pages->get($pageId); ?> <div class="accordion-item"> <h2 class="accordion-header" id="heading<?= $page->id ?>"> <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse<?= $page->id ?>" aria-expanded="false" aria-controls="collapse<?= $page->id ?>"> <?= $page->title ?> (<?= $count ?>) </button> </h2> <div id="collapse<?= $page->id ?>" class="accordion-collapse collapse" aria-labelledby="heading<?= $page->id ?>" data-bs-parent="#internalLinksAccordion"> <div class="accordion-body"> <?php if (!empty($linkedPages[$page->id])): ?> <ul> <?php foreach ($linkedPages[$page->id] as $linkedPage): ?> <?php if ($linkedPage->template != 'service'): ?> <li><a href="<?= $linkedPage->url ?>"><?= $linkedPage->title ?></a></li> <?php endif; ?> <?php endforeach; ?> </ul> <?php else: ?> <p>No internal links found for this page.</p> <?php endif; ?> </div> </div> </div> <?php endif; ?> <?php endforeach; ?> </div> <h3 class="pt-5">Posts without Links to Service and Home Pages</h3> <table class="table"> <thead> <tr> <th>Post Title</th> <th>Edit Link</th> </tr> </thead> <tbody> <?php // echo results foreach ($blogPosts as $post) { if (!$mainPagesLinks->has($post)) { echo "<tr>"; echo "<td><a href=\"{$post->url}\">{$post->title}</a></td>"; echo "<td><a href=\"{$post->editUrl}\">Edit</a></td>"; echo "</tr>"; } } ?> </tbody> </table> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> document.addEventListener('DOMContentLoaded', function () { // Chart data is now defined within the JavaScript scope const chartData = { labels: <?= json_encode($chartLabels); ?>, datasets: [{ data: <?= json_encode($chartValues); ?>, backgroundColor: [ 'rgba(255, 99, 132, 0.8)', 'rgba(54, 162, 235, 0.8)', 'rgba(255, 206, 86, 0.8)', // Add more colors as needed ], }] }; const ctx = document.getElementById('linkCountChart').getContext('2d'); const linkCountChart = new Chart(ctx, { type: 'doughnut', data: chartData, options: { plugins: { legend: { display: true, position: 'bottom', }, } } }); }); </script> Edited May 15 by Leftfield 2 Link to comment Share on other sites More sharing options...
BrendonKoz Posted May 15 Share Posted May 15 This is pretty cool - thanks for sharing! For your color assignment, if this might help, I'd used Chart.js for a PHP-based project in the past and didn't want to have to manually assign colors, so I used the data label to dynamically generate colors for the chart. Here's the helper function I came up with. In my case, I found that the haval128,4 hashtype worked well for color differentiation/contrast, but another option may end up being slightly better with different datasets. ? <?php /** * Convert a string into RGB array (with alpha transparency option) * * @param string $string Any text to be represented as color * @param string $hashtype Hashing algorithm which supports a 32-character output * @return array RGBA color set */ function string_to_rgba($string, $hashtype = 'md2') { // 32-char options: md2, md4, md5, ripemd128, tiger128,3, tiger128,4, haval128,3, haval128,4, haval128,5 if (!in_array($hashtype, ['md2', 'md4', 'md5', 'ripemd128', 'tiger128,3', 'tiger128,4', 'haval128,3', 'haval128,4', 'haval128,5'])){ $hashtype = 'md2'; } $fullhash = hash($hashtype, $string); $hash = substr($fullhash, 0, 8); $colors = str_split($hash, 2); foreach ($colors as $i => $color) { $decimal = hexdec($color); if ($decimal > 230) { $decimal -= 25; } else if ($decimal < 50) { $decimal += 50; } $colors[$i] = $decimal; } $colors[3] = intval($colors[3] / 255 * 100); return $colors; } Link to comment Share on other sites More sharing options...
bernhard Posted May 15 Share Posted May 15 Sounds cool! Do you have any screenshots to share? I guess it also looks cool ? Link to comment Share on other sites More sharing options...
Leftfield Posted May 15 Author Share Posted May 15 @BrendonKozthanks mate! I have to try it. Brilliant! @bernhard Yes, for me, it is a fun little thing but very useful. Here's screenshot attached. 4 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now