Анализ сайта abacus.jasoncameron.dev
Основное Готовность: 75%
Домен
abacus.jasoncameron.dev
Состояние доменного имени
?
Проверяем корректность доменного имени и наличие технических проблем на уровне домена.
Используйте для продвижения только домен второго уровня.
Длина домена велика. Но если вы продвигаете запрос, входящий в название домена, то это хорошо.
Ответ сервера
200 Успешный ответ
HTTP-код ответа и цепочка редиректов
?
Код 200 — страница доступна. Коды 3xx — редиректы (цепочки замедляют загрузку и размывают ссылочный вес). Коды 4xx/5xx — ошибки, поисковик не сможет проиндексировать страницу.
Кол-во редиректов 5 слишком большое! Проверьте настройки сайта и веб-сервера!
Цепочка редиректов:
http://abacus.jasoncameron.dev
301 MovedPermanently
https://abacus.jasoncameron.dev/
308 PermanentRedirect
https://jasoncameron.dev/abacus/
302 Found
https://v2.jasoncameron.dev/abacus
301 MovedPermanently
https://v2.jasoncameron.dev/abacus/
200 OK
Безопасность
Сайт безопасен
Использование HTTPS и SSL-сертификат
?
HTTPS — обязательный стандарт. Google и Яндекс отдают предпочтение защищённым сайтам. Отсутствие SSL или просроченный сертификат ведут к предупреждениям в браузере и снижению позиций.
Не настроен HSTS (Strict-Transport-Security) — рекомендуется включить.
На сайте работает защищенный протокол ssl и сайт открывается по https.
Ssl-сертификат действителен до 04.10.2026 22:45:22.
HTTP автоматически перенаправляется на HTTPS.
Поздравляем! Сайт не содержится в реестре РКН.
Кодировка
UTF-8
Кодировка символов страницы
?
Стандарт — UTF-8. Неправильная кодировка вызывает нечитаемые символы и мешает поисковику корректно распознать текст страницы.
Указана кодировка на странице UTF-8.
Язык
en
Атрибут lang в HTML-теге
?
Атрибут lang (<html lang="ru">) сообщает поисковикам и браузерам, на каком языке написана страница. Помогает при ранжировании в региональном поиске.
Язык документа указан явно: en.
Скорость загрузки
~0,83сек
Время отклика сервера (TTFB)
?
Time To First Byte — время до получения первого байта от сервера. Норма до 200 мс. Медленный отклик ухудшает пользовательский опыт и ранжирование: Яндекс и Google учитывают скорость страниц.
Скорость загрузки сайта 0,83сек оптимальна.
Объем документа
41Кб
Размер HTML-кода страницы
?
Слишком большой HTML замедляет парсинг браузером и сканирование поисковым роботом. Рекомендуется не более 200 Кб.
Объем html-документа 41Кб оптимален.
Структура html-документа корректна.
Ресурсы
Ресурсы: 3
Внешние ресурсы страницы (CSS, JS, изображения)
?
Количество и тип подключённых ресурсов влияют на скорость загрузки. Большое число запросов увеличивает время рендеринга страницы.
Кол-во файлов ресурсов 3 достаточно.
Показать полный список ресурсов
| Тип | Название | Значение |
|---|---|---|
| stylesheet | https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/atom-one-dark.min.css | |
| js | https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js | |
| js | https://www.googletagmanager.com/gtag/js?id=G-98HKBC9VCP |
Серверные заголовки
Кол-во: 17
HTTP-заголовки ответа сервера
?
Заголовки сервера передают браузеру и поисковику служебную информацию: кеширование, безопасность (CSP, HSTS), сжатие (gzip). Правильная настройка ускоряет загрузку и повышает защищённость.
Найдены серверные заголовки 17шт. Подробнее про серверные заголовки.
Показать полный список серверных заголовков
| Ключ | Значение |
|---|---|
| Server | GitHub.com |
| Access-Control-Allow-Origin | * |
| ETag | "6a0e283a-a465" |
| Cache-Control | max-age=600 |
| x-proxy-cache | MISS |
| x-github-request-id | 5232:2840:131CFF:148411:6A8934F0 |
| x-github-edge-region | swedencentral |
| Accept-Ranges | bytes |
| Age | 0 |
| Date | Sat, 22 Aug 2026 05:34:40 GMT |
| Via | 1.1 varnish |
| X-Served-By | cache-bma-essb1270039-BMA |
| X-Cache | MISS |
| x-cache-hits | 0 |
| x-timer | S1787376880.258387,VS0,VE118 |
| Vary | Accept-Encoding |
| x-fastly-request-id | c5e4c097151ec5555fff3e569423d0c6e93892a5 |
CMS
Не определена
Система управления сайтом (движок)
?
CMS — это движок, на котором работает сайт (WordPress, 1C-Bitrix, Tilda и др.). Знание CMS помогает понять возможности SEO-оптимизации и подобрать подходящие инструменты. «Не определена» — вероятно, самописный сайт или нестандартная сборка.
CMS не определена. Вероятно, сайт самописный либо движок надёжно скрыт. Это не ошибка.
Веб-сервер
GitHub.com
Программное обеспечение сервера
?
Веб-сервер — это ПО, которое отдаёт страницы посетителям (nginx, Apache, IIS, LiteSpeed и др.). Определяется по серверным заголовкам ответа (Server, X-Powered-By и т.п.). «Не определён» — сервер намеренно скрывает эти заголовки, это нормальная практика безопасности.
В заголовке Server указано: GitHub.com.
Мета-теги Готовность: 35%
Title
Abacus - A free counting API
Заголовок страницы в браузере и поисковой выдаче
?
Title — главный SEO-заголовок страницы. Влияет на CTR в поиске и ранжирование. Оптимальная длина: 50–70 символов. Ключевые слова — ближе к началу.
Необходимо увеличить число символов в title (текущее значение: 28, оптимально: от 40 до 45)
Дублей словоформ в title не найдено.
Description
Abacus is a free counting service. You can use it to track page hits, and specific events among other things.
Описание страницы в поисковой выдаче (сниппет)
?
Meta Description — текст под заголовком в выдаче. Напрямую на позиции не влияет, но влияет на CTR. Оптимальная длина: 120–160 символов.
Необходимо увеличить число символов в description (текущее значение: 109, оптимально: от 120 до 130)
Keywords
countapi, countapi.xyz, counting, count, api, abacus, free api, visitor count, hit counter, page counter, visitors, number counter api, countapi replacement
Список ключевых слов страницы (устаревший тег)
?
Meta Keywords не учитывается Яндексом и Google для ранжирования с 2009–2012 годов. Заполнение не обязательно, но не вредит. Конкурент может использовать содержимое для анализа.
Keywords установлены.
Канонический Url
https://abacus.jasoncameron.dev
Указывает поисковику основную версию страницы
?
Canonical (rel=canonical) предотвращает проблему дублей страниц. Должен точно совпадать с URL проверяемой страницы. Неправильный canonical может передать ссылочный вес на другую страницу.
Пропишите корректный канонический Url!
Robots
Ошибок нет
Директивы для поисковых роботов на уровне страницы
?
Meta Robots управляет индексацией конкретной страницы: index/noindex — индексировать ли, follow/nofollow — следовать ли по ссылкам. Noindex полностью исключает страницу из поиска.
Meta-тег robots не указан. Страница свободна для индексации.
Адаптивность
width=device-width, user-scalable=no
Настройка масштабирования на мобильных устройствах
?
Тег viewport (<meta name="viewport">) сообщает браузеру, как масштабировать страницу на мобильных. Стандарт: width=device-width, initial-scale=1. Отсутствие — признак отсутствия мобильной версии.
Meta-тег viewport со значением-константой width=device-width задаёт ширину страницы в соответствии с размером экрана.
Meta-тег viewport со значением user-scalable определяет доступность масштабирования страницы пользователем.
Разметка OpenGraph
Кол-во: 8
Мета-теги для красивых превью в соцсетях
?
OpenGraph (og:title, og:description, og:image) управляет тем, как страница выглядит при репосте в социальных сетях и мессенджерах. Отсутствие OG-тегов — невзрачный превью при шеринге.
Разметка OpenGraph задана. Страница оптимизирована под социальные сети.
Показать полный список og мета-тегов
| Тип | Значение |
|---|---|
| og:type | website |
| og:site_name | Abacus |
| og:title | Abacus |
| og:description | Abacus is a free counting service. You can use it to track page hits, and specific events among other things. |
| og:url | https://abacus.jasoncameron.dev |
| og:image | abacus.jasoncameron.dev/favicon.ico |
| og:image:width | 64 |
| og:image:height | 64 |
Все мета-теги
Кол-во: 11
Полный список мета-тегов страницы
?
Таблица всех meta-тегов, включая нестандартные. Позволяет найти опечатки, дубли и лишние теги.
Найдены мета-теги 11шт. Мета-теги не видимы для человека и предназначены для обмена информацией между веб-страницей и поисковыми системами, браузерами и другими веб-службами. С ними роботы 🤖 и устройства ведут себя более ожидаемо.
Показать полный список мета-тегов
| Тип | Название | Значение |
|---|---|---|
| name | viewport | width=device-width, user-scalable=no |
| name | description | Abacus is a free counting service. You can use it to track page hits, and specific events among other things. |
| name | keywords | countapi, countapi.xyz, counting, count, api, abacus, free api, visitor count, hit counter, page counter, visitors, number counter api, countapi replacement |
| property | og:type | website |
| property | og:site_name | Abacus |
| property | og:title | Abacus |
| property | og:description | Abacus is a free counting service. You can use it to track page hits, and specific events among other things. |
| property | og:url | https://abacus.jasoncameron.dev |
| property | og:image | abacus.jasoncameron.dev/favicon.ico |
| property | og:image:width | 64 |
| property | og:image:height | 64 |
Оптимизация Готовность: 82%
Структура
Ошибок нет
Семантические HTML-элементы страницы
?
Проверяет наличие основных структурных элементов: nav, header, footer, main. Корректная семантическая структура помогает поисковику понять архитектуру страницы.
Структура документа корректна (теги <html> и <body> присутствуют по одному на документ).
Контент
Ошибок нет
Объём и качество текстового содержимого
?
Анализирует объём полезного текста на странице. Слишком мало — страница может считаться малополезной. Слишком много — ухудшается читаемость и восприятие.
Слова из title 4 встречаются в тексте достаточно.
Абзацев с текстом 44 достаточно.
Среднее число слов в абзаце 25 достаточно.
Кол-во знаков контента 13574 на странице оптимально.
Кол-во слов 1990 на странице оптимально.
Заголовки
Ошибок нет
Иерархия заголовков H1–H6
?
H1 должен быть один и содержать ключевой запрос. H2–H6 описывают подразделы. Пропуск уровней (H1 → H3) и несколько H1 — типичные ошибки, снижающие понятность страницы для поисковика.
На странице присутствуют заголовки <h1> 6. Это прекрасно.
На странице присутствуют заголовки <h2> 12. Это хорошо.
На странице присутствуют заголовки <h3> 17.
Тошнота
5,29
Насколько одно слово доминирует в тексте
?
Классическая тошнота = √(частота самого повторяющегося слова). Норма до 7–8: текст воспринимается естественно. Выше — поисковик может счесть страницу переспамленной.
Тошнота превышает норму 5. Измените текст страницы!
Академич. тошнота
25,13%
Насколько текст перенасыщен ключевыми словами
?
Академическая тошнота = (частота слова / общее количество слов) × 100%. Показывает долю конкретного слова в тексте. Норма 5–15%.
Академическая тошнота превышает норму 5-15%. Измените текст страницы!
Семантическое ядро
20
Наиболее часто встречающиеся слова на странице
?
Топ слов по частоте использования. Показывает, какие слова доминируют в тексте с точки зрения поисковика.
Контент страницы содержит осмысленный текст и слова.
Показать список слов
| Слово | Кол-во | Частота |
|---|---|---|
| counter | 28 | 1,41% |
| namespace | 19 | 0,95% |
| requests | 13 | 0,65% |
| specify | 12 | 0,60% |
| number | 11 | 0,55% |
| "value": | 11 | 0,55% |
| shield | 10 | 0,50% |
| "error": | 9 | 0,45% |
| default: | 9 | 0,45% |
| jasoncameron | 8 | 0,40% |
| response | 8 | 0,40% |
| bearer | 8 | 0,40% |
| created | 7 | 0,35% |
| please | 7 | 0,35% |
| authorization: | 7 | 0,35% |
| your_admin_key | 7 | 0,35% |
| create | 6 | 0,30% |
| increment | 6 | 0,30% |
| header | 6 | 0,30% |
| seconds | 6 | 0,30% |
Индексация Готовность: 0%
Индексирование
Ошибок нет
Разрешено ли индексирование страницы
?
Проверяет, не закрыта ли страница от индексации через robots.txt, meta robots или X-Robots-Tag. Страница, закрытая от индексации, не появится в поисковой выдаче.
Анкоров на странице 34 оптимально. Поисковые роботы обязательно проиндексируют сайт.
Robots.txt
Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Кол-во редиректов для файла robots.txt 5 слишком большое! Это может вызывать затруднение при индексации поисковыми роботами!
Проверяемая страница не запрещена в robots.txt.
Robots.txt доступен по постоянному адресу
Цепочка редиректов для файла robots.txt:
http://abacus.jasoncameron.dev/robots.txt
301 MovedPermanently
https://abacus.jasoncameron.dev/robots.txt
308 PermanentRedirect
https://jasoncameron.dev/abacus/
302 Found
https://v2.jasoncameron.dev/abacus
301 MovedPermanently
https://v2.jasoncameron.dev/abacus/
200 OK
Показать содержимое robots.txt
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Abacus - A free counting API</title>
<link rel="icon" href="https://abacus.jasoncameron.dev/favicon.svg" type=”image/svg+xml”>
<link rel="icon" href="https://abacus.jasoncameron.dev/favicon.ico" type="image/png">
<link rel="shortcut icon" href="https://abacus.jasoncameron.dev/favicon.ico">
<link rel="canonical" href="https://abacus.jasoncameron.dev">
<meta name="description"
content="Abacus is a free counting service. You can use it to track page hits, and specific events among other things.">
<meta name="keywords"
content="countapi, countapi.xyz, counting, count, api, abacus, free api, visitor count, hit counter, page counter, visitors, number counter api, countapi replacement">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Abacus">
<meta property="og:title" content="Abacus">
<meta property="og:description"
content="Abacus is a free counting service. You can use it to track page hits, and specific events among other things.">
<meta property="og:url" content="https://abacus.jasoncameron.dev">
<meta property="og:image" content="abacus.jasoncameron.dev/favicon.ico">
<meta property="og:image:width" content="64">
<meta property="og:image:height" content="64">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/atom-one-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>
<style>
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body {
color: #606c71;
}
::selection {
background-color: #4688cc;
}
*::selection {
color: white;
}
a {
text-decoration: none;
color: #4688cc;
}
a:hover {
text-decoration: underline;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
.header {
padding: 3rem 4rem;
color: white;
text-align: center;
background-color: #125b96;
background-image: linear-gradient(
55deg,
hsl(211deg 74% 38%) 0%,
hsl(271deg 39% 45%) 38%,
hsl(321deg 86% 36%) 100%
);
box-shadow: inset 0 -2px 2px -2px rgba(0, 0, 0, 0.8);
}
.header .title {
text-shadow: 1px 1px 5px black;
}
.header .legend {
font-size: 1.15rem;
font-weight: normal;
margin-top: 0.4rem;
opacity: 0.7;
}
.container {
max-width: 960px;
margin: auto;
padding: 2rem 4rem;
font-size: 1.1rem;
word-wrap: break-word;
}
.container h1,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
margin-top: 2rem;
margin-bottom: 1rem;
font-weight: normal;
color: #1785aa;
}
.container h1 {
border-bottom: 1px solid rgba(201, 201, 201, 0.33);
}
.container p {
margin-bottom: 1em;
}
.container ol, .container ul {
margin-top: 0;
padding: 0.3rem 2.2rem;
}
.container code {
padding: 2px 4px;
background-color: #efefef;
border-radius: 4px;
}
.container pre {
white-space: pre-wrap;
word-wrap: break-word;
padding: 10px 10px 10px 20px;
border-radius: 0 5px 5px 0;
font-size: 15px;
border-left: 8px solid #ffffff;
color: #707070;
margin-bottom: 1em;
}
.container pre.info {
border-color: #5087af;
background-color: #f3f7f8;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.container pre.success {
border-color: #50af51;
background-color: #f3f8f3;
}
.container pre.fail {
border-color: #af5050;
background-color: #f8f3f3;
}
.container pre, .container pre a, .container .endpoint {
font-family: Monaco, "Lucida Console", monospace;
}
.container table {
display: block;
width: 100%;
overflow: auto;
margin-bottom: 1em;
}
.container table th, .container table td {
padding: 0.5rem 1rem;
border: 1px solid #e9ebec;
min-width: 140px;
}
.container .highlight {
white-space: pre;
font-family: monospace;
font-size: 16px;
border-radius: 2px;
margin-bottom: 1em;
}
.container .highlight code {
background-color: rgba(239, 239, 239, 0.1);
}
.container .highlight * {
font-family: monospace;
}
footer {
padding-top: 1rem;
margin-top: 2rem;
border-top: solid 1px #eff0f1;
}
@media screen and (max-width: 768px) {
.container {
padding: 2rem 2rem;
}
}
</style>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-98HKBC9VCP"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-98HKBC9VCP');
</script>
</head>
<body>
<header class="header">
<img src="https://abacus.jasoncameron.dev/favicon.svg" width="96" alt="A logo of an ABACUS">
<h1 class="title">Abacus</h1>
<h2 class="legend">Counting should be easy, right?</h2>
</header>
<section class="container">
<h2 id="abacus">Abacus - <a href="https://github.com/JasonLovesDoggo/abacus" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github"
viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a></h2>
<p>
This API allows you to create simple numeric counters. IaaS, Integer as a Service.
</p>
<p style="margin-bottom: 2px">It goes down to:</p>
<ul>
<li>Create & Increment counter</li>
<li>View counter's data</li>
</ul>
<p>All counters are “unlisted”—accessible if you know the key but not publicly listed anywhere.</p>
<p>
Want to track the number of hits a page had? Sure.<br>
Want to know the number of users that clicked on the button “Press me”? There you go.
</p>
<p>
So far, <code data-stat-id="keys">...</code> keys have been created and there have been <code
data-stat-id="command_total">...</code> requests served. <code data-stat-id="hits">...</code> of those have
been hits and <code data-stat-id="gets">...</code> have been gets. Abacus is currently on version <code
data-stat-id="version">...</code>.<br>
This page has been visited <code id="visits">...</code> times.
</p>
<h1 id="tldr">TL;DR</h1>
<p>
Each counter is identified inside a <b>namespace</b> with a <b>key</b>.<br>
The namespace should be unique, so its recommend using your site's domain.<br>
Inside each namespace you can generate all the counters you may need.
</p>
<p>The <b>hit</b> endpoint provides increment by one counters directly. Each time its requested the counter will
increase by one:</p>
<pre class="success" style="font-size: 1em">
<a href="https://abacus.jasoncameron.dev/hit/namespace/key" target="_blank">https://abacus.jasoncameron.dev/hit/<code>namespace</code>/<code>key</code></a>⇒ 200 { "value": 1234 }</pre>
<p>Want to start counting right away? Check the examples below!</p>
<h1 id="example">Example</h1>
<p>Let’s say you want to display the amount of page views a site received.</p>
<div class="highlight html"><div id="visits">...</div></div>
<pre class="info">Remember to change <input type="text" id="domain" value="mysite.com" maxlength="64"
autocomplete="off" autocorrect="off" autocapitalize="off"
spellcheck="false"> <label
for="domain">with your site's <b>domain</b></label>.</pre>
<h4>Using JSONP</h4>
<div class="highlight html"><script>
function cb(response) {
document.getElementById('visits').innerText = response.value;
}
</script>
<script async src="https://abacus.jasoncameron.dev/hit/mysite.com/visits?callback=cb"></script>
</div>
<h4>Using XHR</h4>
<div class="highlight js"> var xhr = new XMLHttpRequest();
xhr.open("GET", "https://abacus.jasoncameron.dev/hit/<code class="mysite">mysite.com</code>/visits");
xhr.responseType = "json";
xhr.onload = function() {
document.getElementById('visits').innerText = this.response.value;
}
xhr.send();
</div>
<h4>Using jQuery</h4>
<div class="highlight js">$.getJSON("https://abacus.jasoncameron.dev/hit/<code class="mysite">mysite.com</code>/visits",
function(response) {
$("#visits").text(response.value);
});
</div>
<h3>Multiple pages</h3>
<p>If you want to have a counter for each individual page you can replace <code>visits</code> with a unique
identifier for each page, i.e. <code>index</code>, <code>contact</code>, <code>item-1234</code>. Check <a
href="#format">the right format</a> a key must have.</p>
<p>Alternatively, you can use some reserved words that are replaced server-side.<br>For example, if a request is
made from <code>https://mysite.com/example/page</code>:</p>
<ul>
<li><code>:HOST:</code> will be replaced with <code>mysite.com</code></li>
<li><code>:PATH:</code> will be replaced with <code>examplepage</code></li>
</ul>
<br>
<pre class="info">Note: Reserved words are left padded with dots if their length is less than three.</pre>
<p>So you could use something like:</p>
<pre class="success"><a href="https://abacus.jasoncameron.dev/hit/mysite.com/:PATH:" target="_blank">https://abacus.jasoncameron.dev/hit/<code>mysite.com</code>/:PATH:</a></pre>
<p>Or even more generic (though not recommended):</p>
<pre class="success"><a href="https://abacus.jasoncameron.dev/hit/:HOST:/:PATH:" target="_blank">https://abacus.jasoncameron.dev/hit/:HOST:/:PATH:</a></pre>
<!-- <pre class="info"><b>Important</b>: if you want to know the actual key used you can check the <code>X-Path</code> header.</pre>-->
<h3>Counting events</h3>
<p>You can use the API to count any kind of stuff, let’s say:</p>
<div class="highlight html"><button onclick="clicked()">Press Me!</button>
<script>
function clicked() {
let xhr = new XMLHttpRequest();
xhr.open("GET", "https://abacus.jasoncameron.dev/hit/<code class="mysite">mysite.com</code>/awesomeclick");
xhr.responseType = "json";
xhr.onload = function() {
alert(`This button has been clicked ${this.response.value} times!`);
}
xhr.send();
}
</script>
</div>
<button onclick="clicked()">Press Me!</button>
<script>
function clicked() {
let xhr = new XMLHttpRequest();
xhr.open("GET", "https://abacus.jasoncameron.dev/hit/mysite.com/awesomeclick");
xhr.responseType = "json";
xhr.onload = function () {
alert(`This button has been clicked ${this.response.value} times!`);
}
xhr.send();
}
</script>
<h1 id="faq">FAQ</h1>
<h2>Where is the API documentation?</h2>
<p><a href="#api">Scroll</a> a bit further.</p>
<h2>Is the API free?</h2>
<p>Completely free.</p>
<h2>Rate Limiting?</h2>
<h4>General Rate Limit</h4>
<ul>
<li><strong>Limit:</strong> 30 requests</li>
<li><strong>Window:</strong> 10 seconds</li>
<li><strong>Scope:</strong> Per IP address</li>
</ul>
<p>
This means that each unique IP address is allowed to make a maximum of 30 requests every 10 seconds. Exceeding
this limit will temporarily block further requests from that IP until your limit is up.
</p>
<p>If you require a higher rate limit for legitimate use cases, please contact me at <a
href="mailto:abacus@jasoncameron.dev">abacus@jasoncameron.dev</a>.</p>
<h4>Rate Limit Headers</h4>
<p>The API provides informative headers in responses to help you track your usage:</p>
<ul>
<li><code>RateLimit-Remaining</code>: Number of requests remaining in the current window.</li>
<li><code>RateLimit-Reset</code>: Unix timestamp indicating when the rate limit window resets.</li>
<li><code>RateLimit-Policy</code>: String describing the rate limit policy (e.g., "30;w=10" for 30 requests per 10
seconds).
</li>
<li><code>Retry-After</code>: Number of ms to wait before retrying (included when rate limited).</li>
</ul>
<h4>Rate Limit Exceeded</h4>
When you exceed the rate limit, the API will respond with a <code>429 Too Many Requests</code> status code response
similar to:
<pre style="margin-top: 1vh" class="success">{
"error": "Too many requests. Try again in 2s"
}
</pre>
<h2>Can I delete a key?</h2>
<p>If you originally created the key using the <a href="#create">/create endpoint</a>, then yes, you can delete the
key and all data associated with it by using the <a href="#delete"> /delete</a> endpoint along with your admin
key.</p>
<h2>Will I blow up the Abacus server?</h2>
<p>Abacus is using <a href="https://valkey.io/" target="_blank">Valkey</a> as a database, a rapid key-value
solution.<br>If you are planning to make <b>tens of thousands</b> of requests, I'll be glad if you <a
href="mailto:abacus@jasoncameron.dev">email me</a> letting me know.</p>
<h2 id="contact">Issues/Contact</h2>
<p>If you have issues, suggestions or just want to contact me, shoot me <a href="mailto:abacus@jasoncameron.dev"
target="_blank">an email</a> or <a
href="https://github.com/JasonLovesDoggo/abacus/issues/new">create a GitHub issue.</a></p>
<h1 id="api">API</h1>
<h2>Authentication & Rate Limiting</h2>
<p>Endpoints requiring administrative actions (delete, set, reset, update) need an admin key passed in the
`Authorization` header as a Bearer token. You get this admin key when creating a counter via <a href="#create">/create</a>.
</p>
<p>Rate limiting is in place to ensure fair usage: 30 requests per IP address every 10 seconds.</p>
<h2>Namespaces</h2>
<p>Namespaces are used to avoid name collisions.
You can specify a namespace when creating a key.
It's recommended to use the domain of your app as the namespace to prevent conflicts with other websites.<br>If
you don't
specify a namespace, the key is assigned to the <code>default</code> namespace.
You don't need to specify the `default` namespace in your requests.</p>
<h2>Endpoints</h2>
<p>
All requests support <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank">cross-origin
resource sharing</a> (CORS) and SSL.
</p>
<p>Base API path: <a href="https://abacus.jasoncameron.dev" target="_blank">https://abacus.jasoncameron.dev</a></p>
<p>In case of a server failure, the API will send:</p>
<pre class="fail">⇒ 500 { "error": "Error description" }</pre>
<h3 class="endpoint">/healthcheck</h3>
<p>Check the health and uptime of the API.</p>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/healthcheck" target="_blank">GET /healthcheck</a>
⇒ 200 { "status": "ok", "uptime": "1h23m45s" }</pre>
<h3 class="endpoint">/docs</h3>
<p>Redirects to the API documentation.</p>
<h3 class="endpoint">/get/:namespace/:key</h3>
<p>Retrieve the current value of a counter. Optionally specify the namespace.</p>
<pre class="info">If you want to use JSONP, please pass in the callback via the ?callback query param (e.g. ?callback=myjsfunction) </pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/get/test" target="_blank">GET /get/test</a>
⇒ 200 { "value": 42 }</pre>
<pre class="fail">
<a href="https://abacus.jasoncameron.dev/get/nonexisting" target="_blank">GET /get/nonexisting</a>
⇒ 404 { "error": "Key not found" }</pre>
<h3 class="endpoint">/get/:namespace/:key/shield</h3>
<p>Retrieve the current value of a counter as a SVG shield.</p>
<h4 id="shieldquery">Query Parameters:</h4>
<ul>
<li><code>bgcolor=007ec6</code>: Background color (default: 007ec6 - blue)
<ul>
<li>Accepts hex color codes (with or without # prefix) like: 007ec6, ff5500, etc.</li>
</ul>
</li>
<li><code>textcolor=fff</code>: Text color (default: fff - white)
<ul>
<li>Accepts hex color codes (with or without # prefix) like: fff, 000, etc.</li>
</ul>
</li>
<li><code>text=counter</code>: Custom text label for the shield (default: counter)</li>
<li><code>style=flat</code>: Shield style (default: flat)
<ul>
<li>Regular styles: flat, flat-square, plastic</li>
<li>Simple styles (only show count value): flat-simple, flat-square-simple, plastic-simple</li>
</ul>
</li>
<li><code>fontsize=11</code>: Font size for the shield text (default: 11)
<ul>
<li>Must be greater than 3 for proper rendering</li>
<li>Automatically scales badge elements to maintain proper proportions</li>
</ul>
</li>
<li><code>font=verdana</code>: Font family for the shield text (default: verdana)
<ul>
<li>Available fonts: verdana, verdana-bold, verdana-bold-italic, arial, arial-bold, arial-italic,
arial-bold-italic, courier-new, jetbrains-mono
</li>
</ul>
</li>
</ul>
<pre class="info">Note that the <code>text</code> parameter will be ignored if a simple style is chosen as those styles only display the counter value.</pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/get/test/default/shield" target="_blank">GET /get/test/default/shield</a>
⇒ 200<br><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="82" height="20"
role="img" aria-label="counter: 1"><title>counter: 1</title><linearGradient id="s" x2="0" y2="100%"><stop
offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath
id="r"><rect width="82" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="52"
height="20"
fill="#555"/><rect
x="52" width="30" height="20" fill="#007ec6"/><rect width="82" height="20" fill="url(#s)"/></g><g
fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif"
text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="270" y="150" fill="#010101"
fill-opacity=".3" transform="scale(.1)"
textLength="408">counter</text><text x="270"
y="140"
transform="scale(.1)"
fill="#fff"
textLength="408">counter</text><text
aria-hidden="true" x="660" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)"
textLength="200">1</text><text x="660" y="140" transform="scale(.1)" fill="#fff"
textLength="200">1</text></g></svg></pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/get/test/default/shield?bgcolor=e05d44&text=visits&style=plastic&fontsize=12&font=arial&textcolor=ffff00"
target="_blank">GET /get/test/default/shield?bgcolor=e05d44&text=visits&style=plastic&fontsize=12&font=arial&textcolor=ffff00</a>
⇒ 200<br><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="18"
role="img" aria-label="visits: 1"><title>visits: 1</title><linearGradient id="s" x2="0" y2="100%"><stop
offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop
offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000"
stop-opacity=".5"/></linearGradient><clipPath id="r"><rect
width="53" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="37" height="18"
fill="#555"/><rect x="37"
width="16"
height="18"
fill="#e05d44"/><rect
width="53" height="18" fill="url(#s)"/></g><g fill="#ffff00" text-anchor="middle"
font-family="Arial,Geneva,DejaVu Sans,sans-serif"
text-rendering="geometricPrecision" font-size="120"><text
aria-hidden="true" x="195" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="266">visits</text><text
x="195" y="130" transform="scale(.1)" fill="#ffff00" textLength="266">visits</text><text aria-hidden="true"
x="440" y="140"
fill="#010101"
fill-opacity=".3"
transform="scale(.1)"
textLength="66">1</text><text
x="440" y="130" transform="scale(.1)" fill="#ffff00" textLength="66">1</text></g></svg></pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/get/test/default/shield?style=flat-simple&bgcolor=4c1" target="_blank">GET /get/test/default/shield?style=flat-simple&bgcolor=4c1</a>
⇒ 200<br><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="20"><linearGradient
id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1"
stop-opacity=".1"/></linearGradient><mask
id="round"><rect width="30" height="20" rx="3" fill="#fff"/></mask><g mask="url(#round)"><rect width="30"
height="20"
fill="#4c1"/><rect
width="30" height="20" fill="url(#smooth)"/></g><g fill="#fff" text-anchor="middle"
font-family="Verdana,DejaVu Sans,sans-serif"
font-size="11"><text x="15" y="15" fill="#010101"
fill-opacity=".3">1</text><text
x="15" y="15">1</text></g></svg></pre>
<pre class="fail">
<a href="https://abacus.jasoncameron.dev/get/test/default/shield?bgcolor=purple" target="_blank">GET /get/test/default/shield?bgcolor=purple</a>
⇒ 400 { "error": "invalid background color: 'purple' is not a valid hex color (should be like 'fff' or 'ff5500')" }</pre>
<pre class="fail">
<a href="https://abacus.jasoncameron.dev/get/nonexisting/default/shield" target="_blank">GET /get/nonexisting/default/shield</a>
⇒ 404 { "error": "Key not found" }</pre>
<h3 class="endpoint">/hit/:namespace/:key</h3>
<p>Increment a counter by 1 and return the new value. If the counter doesn't exist, it will be created. Optionally
specify a namespace.</p>
<pre class="info">If you want to use JSONP, please pass in the callback via the ?callback query param (e.g. ?callback=myjsfunction) </pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/hit/mysite.com/visits" target="_blank">GET /hit/mysite.com/visits</a> (value was 35)
⇒ 200 { "value": 36 }</pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/hit/nonexisting" target="_blank">GET /hit/nonexisting</a> (key is created)
⇒ 200 { "value": 1 }</pre>
<h3 class="endpoint">/hit/:namespace/:key/shield</h3>
<p>Increment a counter by 1 and return the new value as a SVG shield. If the counter doesn't exist, it will be
created.</p>
<h4>Query Parameters:</h4>
<p>Supports the same query parameters as the <a href="#shieldquery"><code>/get/:namespace/:key/shield</code></a>
endpoint:</p>
<ul>
<li><code>bgcolor=007ec6</code>: Background color (default: 007ec6 - blue)</li>
<li><code>textcolor=fff</code>: Text color (default: fff - white)</li>
<li><code>text=counter</code>: Custom text label for the shield (default: counter)</li>
<li><code>style=flat</code>: Shield style (flat, flat-square, plastic, flat-simple, flat-square-simple,
plastic-simple)
</li>
<li><code>fontsize=11</code>: Font size for the shield text (must be > 3)</li>
<li><code>font=verdana</code>: Font family for the shield text</li>
</ul>
<pre class="info">For improved badge appearance at different font sizes, padding and corner radius are automatically scaled proportionally.</pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/hit/mysite.com/visits/shield"
target="_blank">GET /hit/mysite.com/visits/shield</a> (value was 35)
⇒ 200<br><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="75" height="20"
role="img" aria-label="counter: 36"><title>counter: 36</title><linearGradient id="s" x2="0" y2="100%"><stop
offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath
id="r"><rect width="75" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="52"
height="20"
fill="#555"/><rect
x="52" width="23" height="20" fill="#007ec6"/><rect width="75" height="20" fill="url(#s)"/></g><g
fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif"
text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="270" y="150" fill="#010101"
fill-opacity=".3" transform="scale(.1)"
textLength="408">counter</text><text x="270"
y="140"
transform="scale(.1)"
fill="#fff"
textLength="408">counter</text><text
aria-hidden="true" x="625" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="133">36</text><text
x="625" y="140" transform="scale(.1)" fill="#fff" textLength="133">36</text></g></svg>
</pre>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/hit/mysite.com/visits/shield?style=flat-square-simple&bgcolor=97ca00&textcolor=000"
target="_blank">GET /hit/mysite.com/visits/shield?style=flat-square-simple&bgcolor=97ca00&textcolor=000</a>
⇒ 200<br><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="23" height="20"><g><rect
width="23" height="20" fill="#97ca00"/></g><g fill="#000" text-anchor="middle"
font-family="Verdana,DejaVu Sans,sans-serif" font-size="11"><text
x="11.5" y="15">37</text></g></svg></pre>
<h3 class="endpoint">/stream/:namespace/*key</h3>
<p>Stream updates to a counter's value using <a
href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Receiving_events_from_the_server"
target="_blank">Server-Sent Events (SSE)</a>. This means you get updated right as a key is updated instead
of having to poll. Optionally specify a namespace.</p>
<pre class="success">
<a href="https://abacus.jasoncameron.dev/stream/mysite.com/visits" target="_blank">GET /stream/mysite.com/visits</a>
⇒ data: {"value": 36}
</pre>
<h3 id="create" class="endpoint">/create/:namespace/*key</h3>
<p>Create a new counter with an optional initial value (default 0). Specify both namespace and key. </p>
<pre class="info">Note about <b>admin_key</b>: this is the only time you will be able to see it, if you lose the key then you lose access to control the counter. </pre>
<pre class="info">Note about <b>expiration</b>: Every time a key is accessed its expiration is set to <b>6 months</b>. So don't worry, if you still using it, it won't expire.</pre>
<pre class="info" id="format">Keys and namespaces must have at least 3 characters and less or equal to 64. Keys and namespaces must match: <b>^[A-Za-z0-9_-.]{3,64}$</b></pre>
<br/>
<pre class="success">
GET /create/myapp/newcounter?initializer=10
⇒ 201 {"key": "newcounter", "namespace": "myapp", "admin_key": "YOUR_ADMIN_KEY", "value": 10}</pre>
<pre class="fail">
GET /create/myapp/alreadyexists
⇒ 409 { "error": "Key already exists, please use a different key." }</pre>
<h3 class="endpoint">/create/</h3>
<p>Create a new counter with a random namespace and key. This endpoint does not take any parameters.</p>
<pre class="success">
GET /create
⇒ 201 {"key": "randomkey", "namespace": "randomnamespace", "admin_key": "YOUR_ADMIN_KEY", "value": 0}</pre>
<h3 class="endpoint">/info/:namespace/*key</h3>
<p>Get detailed information about a counter, including its value, key, expiration, etc. Optionally specify the
namespace.</p>
<pre class="success">
GET /info/existing
⇒ 200 {
"value": 42, // Current counter value
"full_key": "K:default:existing", // The full DB key (K:namespace:key)
"is_genuine": true, // Indicates if the counter was created with an admin key (false) or not (true)
"expires_in": 172800, // Time to live (TTL) in seconds
"expires_str": "2d", // TTL in a human-readable format
"exists": true // Whether the key exists in the DB
}</pre>
<pre class="fail">
GET /info/nonexisting
⇒ 404 {
"value": -1,
"full_key": "default:nonexisting",
"is_genuine": true,
"expires_in": -2e-9,
"expires_str": "-2ns", // When the server received the request compared to when it output a response.
"exists": false
}</pre>
<h3 id="delete" class="endpoint">/delete/:namespace/*key (Requires Admin Key)</h3>
<p>Delete a counter. Specify both namespace and key. Include the admin key in the `Authorization` header.</p>
<pre class="success">
POST /delete/myapp/mycounter
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 200 { "status": "ok", "message": "Deleted key: myapp:mycounter" }
</pre>
<h3 class="endpoint">/set/:namespace/*key?value=:value (Requires Admin Key)</h3>
<p>Set the value of a counter, overwriting the existing value. Specify both namespace and key, and provide the
`value` query parameter. Include the admin key in the `Authorization` header.</p>
<pre class="success">
POST /set/myapp/mycounter?value=15
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 200 { "value": 15 }
</pre>
<pre class="fail">
POST /set/myapp/nonexisting?value=15
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 404 { "error": "Key does not exist, please use a different key." }
</pre>
<h3 class="endpoint">/reset/:namespace/*key (Requires Admin Key)</h3>
<p>Reset a counter to 0. Specify both namespace and key. Include the admin key in the `Authorization` header.</p>
<pre class="success">
POST /reset/myapp/mycounter
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 200 { "value": 0 }
</pre>
<pre class="fail">
POST /reset/myapp/nonexisting
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 404 { "error": "Key doesnot exist, please use a different key." }
</pre>
<h3 class="endpoint">/update/:namespace/*key?value=:amount (Requires Admin Key)</h3>
<p>Increment or decrement a counter by the specified amount. Specify both namespace and key, and provide the value
query parameter (positive to increment, negative to decrement). Include the admin key in the Authorization
header.</p>
<pre class="success">
POST /update/myapp/mycounter?value=5
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 200 { "value": 20 } // Assuming the previous value was 15
</pre>
<pre class="fail">
POST /update/myapp/nonexisting?value=-3
Authorization: Bearer YOUR_ADMIN_KEY
⇒ 404 { "error": "Key does not exist, please first create it using /create." }
</pre>
<h3 class="endpoint">/stats</h3>
<p>Gives some info about the server and database. The "commands" stats are updated every 30s per shard</p>
<pre class="success">
GET /stats/
⇒ 200 {
"commands": {
"create": 20394, // total number of /create's
"get": 403232, // total number of /get's
"hit": 703232, // total number of /hit's
"total": 2003058 // total number of requests served
},
"db_uptime": "5558", // database uptime in seconds
"db_version": "6.0.16", // database version
"expired_keys__since_restart": "130", // number of keys expired since db's last restart
"key_misses__since_restart": "205", // number of keys not found since db's last restart
"total_keys": 87904, // total number of keys created
"version": "1.6.0", // Abacus's version
"shard": "boujee-coorgi", // Handler shard
"uptime": "1h23m45s" // shard uptime
}
</pre>
<footer style="text-align: center; gap: 2rem; display: flex; flex-direction: row; align-items: center; justify-content: center">
<h1 style="all: unset">
made by <a href="https://jasoncameron.dev">Jason Cameron</a> as a replacement for <a
href="https://countapi.xyz">CountAPI</a>.</h1>
<h2 style="all: unset">
<a href="https://github.com/JasonLovesDoggo/abacus" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github"
viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a>
</h2>
</footer>
<script>
let formatter = Intl.NumberFormat('en', {notation: 'compact'});
document.querySelectorAll('div.code').forEach(el => {
// then highlight each
hljs.highlightElement(el);
});
function request(url, callback) {
var req = new XMLHttpRequest();
req.open("GET", url);
req.responseType = 'json';
req.onload = function () {
if (this.status === 200 && typeof this.response === 'object')
callback(this.response);
else
callback(null);
}
req.send();
}
function stats() {
request("https://abacus.jasoncameron.dev/stats", function (obj) {
if (obj) {
const commands = obj["commands"];
const keys = obj["total_keys"];
Array.from(document.querySelectorAll(`*[data-stat-id="version"]`)).map(o => o.innerText = obj["version"]);
Array.from(document.querySelectorAll(`*[data-stat-id="command_total"]`)).map(o => {
o.innerText = formatter.format(commands["total"])
o.title = `${commands["total"].toLocaleString()} requests served`
});
Array.from(document.querySelectorAll(`*[data-stat-id="hits"]`)).map(o => {
o.innerText = formatter.format(commands["hit"])
o.title = `${commands["hit"].toLocaleString()} hits`
});
Array.from(document.querySelectorAll(`*[data-stat-id="gets"]`)).map(o => {
o.innerText = formatter.format(commands["get"])
o.title = `${commands["get"].toLocaleString()} gets`
});
Array.from(document.querySelectorAll(`*[data-stat-id="keys"]`)).map(o => {
o.innerText = formatter.format(keys)
o.title = `${keys.toLocaleString()} keys created`
});
}
});
}
stats();
request("https://abacus.jasoncameron.dev/hit/abacus/visits", function (obj) {
if (obj) {
document.getElementById('visits').innerText = formatter.format(obj.value);
document.getElementById('visits').title = `${obj.value.toLocaleString()} visits`
}
});
function updateDomain(domain) {
document.querySelectorAll('.mysite').forEach(function (e) {
e.innerText = domain;
});
}
hljs.configure({tabReplace: ' '});
document.addEventListener('DOMContentLoaded', function () {
updateDomain("mysite.com");
document.getElementById('domain').addEventListener('input', function (e) {
e.target.value = e.target.value.replace('https://', '').replace('http://', '').replace(/[^A-Za-z0-9_\-.]/g, '');
updateDomain(e.target.value);
});
document.querySelectorAll('div.highlight').forEach(function (block) {
hljs.highlightBlock(block);
});
});
</script>
</section>
</body>
</html>
Sitemap
Кол-во: 0
XML-карта сайта для поисковиков
?
Sitemap.xml помогает поисковику быстрее находить и индексировать страницы. Особенно важен для крупных сайтов и новых страниц, на которые ещё нет входящих ссылок.
Robots.txt не содержит ссылку на карту сайта. Рекомендуется добавить карту сайта и указать ссылку на нее в robots.txt.
Внутренние ссылки
Кол-во: 17
Ссылки на другие страницы своего сайта
?
Внутренние ссылки распределяют ссылочный вес между страницами и помогают поисковику обходить сайт. Пустые анкоры и ссылки на запрещённые robots.txt страницы — типичные ошибки.
Внутренних ссылок на странице 17 оптимально.
Внутренние ссылки не запрещены к индексации в robots.txt.
Показать внутренние ссылки
| Url | Анкор | Состояние | Анализировать |
|---|---|---|---|
| /hit/namespace/key |
https://abacus.jasoncameron.dev/hit/<code>namespace</code>/<code>key</code>
|
|
Анализировать url |
| /hit/mysite.com/:PATH: |
https://abacus.jasoncameron.dev/hit/<code>mysite.com</code>/:PATH:
|
|
Анализировать url |
| /hit/:HOST:/:PATH: |
https://abacus.jasoncameron.dev/hit/:HOST:/:PATH:
|
|
Анализировать url |
|
https://abacus.jasoncameron.dev
|
|
Анализировать url | |
| /healthcheck |
GET /healthcheck
|
|
Анализировать url |
| /get/test |
GET /get/test
|
|
Анализировать url |
| /get/nonexisting |
GET /get/nonexisting
|
|
Анализировать url |
| /get/test/default/shield |
GET /get/test/default/shield
|
|
Анализировать url |
| /get/test/default/shield?bgcolor=e05d44&text=visits&style=plastic&fontsize=12&font=arial&textcolor=ffff00 |
GET /get/test/default/shield?bgcolor=e05d44&text=visits&style=plastic&fontsize=12&font=arial&textcolor=ffff00
|
|
Анализировать url |
| /get/test/default/shield?style=flat-simple&bgcolor=4c1 |
GET /get/test/default/shield?style=flat-simple&bgcolor=4c1
|
|
Анализировать url |
| /get/test/default/shield?bgcolor=purple |
GET /get/test/default/shield?bgcolor=purple
|
|
Анализировать url |
| /get/nonexisting/default/shield |
GET /get/nonexisting/default/shield
|
|
Анализировать url |
| /hit/mysite.com/visits |
GET /hit/mysite.com/visits
|
|
Анализировать url |
| /hit/nonexisting |
GET /hit/nonexisting
|
|
Анализировать url |
| /hit/mysite.com/visits/shield |
GET /hit/mysite.com/visits/shield
|
|
Анализировать url |
| /hit/mysite.com/visits/shield?style=flat-square-simple&bgcolor=97ca00&textcolor=000 |
GET /hit/mysite.com/visits/shield?style=flat-square-simple&bgcolor=97ca00&textcolor=000
|
|
Анализировать url |
| /stream/mysite.com/visits |
GET /stream/mysite.com/visits
|
|
Анализировать url |
Внешние ссылки
Кол-во: 8
Ссылки на сторонние сайты
?
Исходящие внешние ссылки передают часть ссылочного веса на чужие сайты. Ссылки на авторитетные ресурсы безопасны; ссылки на мусорные сайты могут навредить репутации страницы.
Внешних ссылок на странице 8 слишком много. Спрячьте лишние ссылки в тег noindex или атрибут rel='nofollow'!
Показать внешние ссылки
| Url | Анкор | Анализировать |
|---|---|---|
| github.com |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github" viewbox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"></path>
</svg>
|
Анализировать url |
| valkey.io |
Valkey
|
Анализировать url |
| github.com |
create a GitHub issue.
|
Анализировать url |
| developer.mozilla.org |
cross-origin
resource sharing
|
Анализировать url |
| developer.mozilla.org |
Server-Sent Events (SSE)
|
Анализировать url |
| jasoncameron.dev |
Jason Cameron
|
Анализировать url |
| countapi.xyz |
CountAPI
|
Анализировать url |
| github.com |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github" viewbox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"></path>
</svg>
|
Анализировать url |
Конкуренты Готовность: 0%
Конкуренты в Яндексе
Кол-во: 0
Топ сайтов-конкурентов в Яндексе
?
Сайты, чаще всего появляющиеся в ТОПе Яндекса по запросам из семантического ядра этой страницы.
Мы не нашли у вас конкурентов в Яндексе. Сайт или очень молодой или плохо продвигается.
Конкурентов в ТОП-10 Яндекса не нашлось.
Конкуренты в Google
Кол-во: 0
Топ сайтов-конкурентов в Google
?
Сайты, чаще всего появляющиеся в ТОПе Google по запросам из семантического ядра этой страницы.
Конкуренты в Google тоже не найдены. Займитесь продвижением сайта!
Конкурентов в ТОП-10 Google не нашлось.
ЗоЗПП: права потребителей Готовность: 100%
Нарушения
Не выявлены
Признаков дистанционной продажи товаров (интернет-магазина) не обнаружено — требования ЗоЗПП о раскрытии информации продавца к сайту не применяются. Нарушений нет.
ФЗ-149: рекомендательные технологии Готовность: 100%
Нарушения
Не выявлены
Рекомендательные блоки («с этим покупают», «похожие товары» и т.п.) на сайте не обнаружены — требования ст. 10.7 ФЗ-149 к сайту не применяются. Нарушений нет.
ФЗ-38: реклама Готовность: 100%
Нарушения
Не выявлены
Рекламных тематик с обязательными оговорками (медицина, БАД, кредиты и займы, новостройки) на сайте не обнаружено. Нарушений нет.
ФЗ-436: защита детей Готовность: 100%
Нарушения
Не выявлены
Признаков информационной продукции (новости, видео, книги, игры, курсы) не обнаружено — обязательная возрастная маркировка по ФЗ-436 сайту не требуется. Нарушений нет.
Вердикт
Анализ сайта abacus.jasoncameron.dev, слабо оптимизирован на 48%. Для хорошей оптимизации и выхода на первые места в поиске требуется:
Исправьте ошибки в мета-тегах.
Исправьте ошибки индексации.
Поделитесь с друзьями: