© 2008-2024 г.
Все права защищены

Счётчик просмотров на сайте без БД на PHP, JS

Не так давно я писал пост как создать лайки для блога без подключения к БД и теперь решил рассказать как создать счётчик просмотров страниц на PHP и JS. Статья рассчитана на людей, которые имеют представление об основах PHP и JS и навыки подключения файлов.

Содержание статьи

Обработчик PHP

Мы должны создать два файла, который один будет считать просмотры по схеме 1 IP = 1 просмотр и записывать данные в файл view.json.

Файл update_views.php

<?php
header('Content-Type: application/json');

$file = 'view.json';
$data = json_decode(file_get_contents($file), true);

$postId = $_POST['postId'];
$userIp = $_SERVER['REMOTE_ADDR'];

if (!isset($data[$postId])) {
    $data[$postId] = ['views' => 0, 'ips' => []];
}

if (!in_array($userIp, $data[$postId]['ips'])) {
    $data[$postId]['views']++;
    $data[$postId]['ips'][] = $userIp;
    file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
}

echo json_encode(['views' => $data[$postId]['views']]);
?>

Как вы видите мы создаем файл view.json в который записываем данные: ip посетителя, id страницы и количество просмотров.

Файл get_views.php

<?php
header('Content-Type: application/json');

$file = 'view.json';
$data = json_decode(file_get_contents($file), true);

$postId = $_GET['postId'];

if (isset($data[$postId])) {
    echo json_encode(['views' => $data[$postId]['views']]);
} else {
    echo json_encode(['views' => 0]);
}
?>

Этот файл нужен, чтобы получить данные из файла view.json и передать просмотры каждой страницы в счетчик

JS обработка счетчика

Первый скрипт обрабатывает данные  при открытии страницы, а у меня это статья на этом блоге.

document.addEventListener('DOMContentLoaded', function() {
    const pageviewElement = document.querySelector('.post .pageview-count');
    if (pageviewElement) {
        const postId = pageviewElement.getAttribute('data-id');

        fetch('/update_views.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: `postId=${postId}`
        })
        .then(response => response.json())
        .then(data => {
            pageviewElement.textContent = data.views;
        })
        .catch(error => {
            console.error('Error:', error);
        });
    }
});

В этой строке вам нужно прописать нужные селекторы до счетчика

const pageviewElement = document.querySelector('.post .pageview-count');

У меня HTML структура блоговой страницы следующая:

<main class="post">
<article class="content">
...
<!-- Счетчик просмотров -->
<span class="pageview-count" data-id="{{id}}">0</span>
</acrticle>
</main>

Поэтому в подключении JS я указал .post .pageview-count, который находит класс post и далее сам счетчик внутри статьи.

Строка fetch('/update_views.php', { создает асинхронный POST запрос к PHP обработчику, который лежит у меня в корне сайта. Вы можете указать свой путь до файла update_views.php

Сам скрипт вы можете подключить на странице вашего сайта, либо в <head></head>, а если это Wordpress, то это файлы page.php, post.php.

Второй скрипт JS обновляет счетчик просмотров на общих страницах, где содержатся записи статей, тегов и т.д.

document.addEventListener('DOMContentLoaded', function() {
    const pageviewElements = document.querySelectorAll('.pageview-count');

    function updateViewCount(element, postId) {
        fetch(`/get_views.php?postId=${postId}`)
        .then(response => response.json())
        .then(data => {
            element.textContent = data.views;
        })
        .catch(error => {
            console.error('Error:', error);
        });
    }

    pageviewElements.forEach(element => {
        const postId = element.getAttribute('data-id');
        updateViewCount(element, postId);
    });

    // Обновляем счетчики каждые 10 секунд
    setInterval(() => {
        pageviewElements.forEach(element => {
            const postId = element.getAttribute('data-id');
            updateViewCount(element, postId);
        });
    }, 10000);
});

Строка fetch(`/get_views.php?postId=${postId}`) создает асинхронный GET запрос к PHP обработчику get_views.php, который лежит у меня в корне сайта и получает данные о количестве просмотров каждой страницы. Вы можете указать свой путь до файла. Также счетчик обновляется каждые 10 секунд. Этот параметр вы можете отрегулировать сами.

HTML подключение счётчика

У меня на сайте, где работает данный счётчик подключено такой строкой:

<span class="pageview-count" data-id="{{id}}">0</span>

Что такое data-id? Это атрибут, который получает из переменной {{id}} id страницы. В вашем проекте получение id страницы может быть реализовано по другому, а если у вас CMS, то смотрите документацию по получению id. Данным кодом можно выводить счетчик на нужных страницах и в списке блога.

Пример получения id записи блога в CMS Wordpress

Внутри записи (single.php)

<?php
get_header();

if (have_posts()) :
    while (have_posts()) : the_post();
        $post_id = get_the_ID();
        ?>
        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <header class="entry-header">
                <h1 class="entry-title"><?php the_title(); ?></h1>
            </header>
            <div class="entry-content">
                <?php the_content(); ?>
                <span class="pageview-count" data-id="<?php echo $post_id; ?>">0</span>
            </div>
        </article>
        <?php
    endwhile;
endif;

get_footer();
?>

В списке записей (index.php или archive.php)

<?php
get_header();

if (have_posts()) :
    while (have_posts()) : the_post();
        $post_id = get_the_ID();
        ?>
        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <header class="entry-header">
                <h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
            </header>
            <div class="entry-content">
                <?php the_excerpt(); ?>
                <span class="pageview-count" data-id="<?php echo $post_id; ?>">0</span>
            </div>
        </article>
        <?php
    endwhile;
endif;

get_footer();
?>

Файл view.json

Достаточно создать пустой файл и положить в корень сайта, либо в другую директорию по вашему желанию и разрешить запись в него cmod 777. Доступ к данному файлу нужно ограничить, чтобы никто не смог посмотреть записанные данные. Делается это путем внесения кода в файле .htaccess:

 <Files view.json>
 order allow,deny
 deny from all
 </Files>

Теперь при переходе site.ru/view.json будет отдаваться 403 ошибка.

Оформление счетчика как у меня в блоге

HTML:

<div class="view-counter">
  <svg width="22" height="16" viewBox="0 0 22 16" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M1.42012 8.71318C1.28394 8.49754 1.21584 8.38972 1.17772 8.22342C1.14909 8.0985 1.14909 7.9015 1.17772 7.77658C1.21584 7.61028 1.28394 7.50246 1.42012 7.28682C2.54553 5.50484 5.8954 1 11.0004 1C16.1054 1 19.4553 5.50484 20.5807 7.28682C20.7169 7.50246 20.785 7.61028 20.8231 7.77658C20.8517 7.9015 20.8517 8.0985 20.8231 8.22342C20.785 8.38972 20.7169 8.49754 20.5807 8.71318C19.4553 10.4952 16.1054 15 11.0004 15C5.8954 15 2.54553 10.4952 1.42012 8.71318Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
      <path d="M11.0004 11C12.6573 11 14.0004 9.65685 14.0004 8C14.0004 6.34315 12.6573 5 11.0004 5C9.34355 5 8.0004 6.34315 8.0004 8C8.0004 9.65685 9.34355 11 11.0004 11Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
  </svg>
  <span class="pageview-count" data-id="{{id}}">0</span>
</div>

CSS:

.view-counter {
    display: flex;
    align-items: center;
}
.view-counter svg {
    margin-right: 5px;
}

Готовые файлы для скачивания

Для удобства я подготовил архив со всеми файлам, достаточно скачать и настроить по моей инструкции, а если есть вопросы пишите в комментариях.

Привет Username! Я Алексей Костюк
14 лет занимаюсь тем, что помогаю людям создавать сайты и дизайн, настраивать рекламу, продвигать проекты в Интернете. Ну и иногда еще принтер починить ;) Я создал этот блог, чтобы делить своим опытом и мыслями, а если вам нужна моя помощь, то вы знаете, где меня искать. Перейти на мой сайт