Настройка title для каждой страницы сайта на WordPress без плагинов

Просто добавьте этот код в functions.php вашей темы:

function your_document_title($title) {
  $sep = ' | ';
  $array = [];
  $term = get_queried_object();
 
  global $page;
 
  if (is_singular()) {
    if ($page) {
      array_push($array, 'Часть '.intval($page));
    }
    array_push($array, get_the_title($term));
  }
  else if (is_paged()) {
    array_push($array, 'Страница ' . intval(get_query_var('paged')));
  }
 
 if (is_search()) {
    array_push($array, 'Результат поиска по запросу "'.esc_html($_GET['s'].'"'));
  }
  else if (is_category($term)) {
    array_push($array, 'Категория "' . $term->name . '"');
  }
  else if (is_tag($term)) {
    array_push($array, 'Метка "' . $term->name . '"');
  }
 
  array_push($array, get_bloginfo('name'));
 
  if (is_front_page() && !is_paged()) {
    array_push($array, get_bloginfo('description'));
  }
 
  return implode($sep, $array);
}
add_filter('document_title', 'your_document_title');

Правила такие:

  • для одиночных постов — «Название поста»
  • для страницы категории выводится — Категория «Название»
  • для страницы тега выводится — Метка «Название»
  • для главной страницы «Название сайта | Описание сайта»
  • для постов разбитых на части добавляется «Часть N» в начале
  • для страница поиска типа /s=QUERY «Результат поиска QUERY»
  • для страниц пагинации типа /page/N добавляется «Страница N» в начале
  • для всех страниц добавляется информация из поля Настройки->Общие->Название сайта
  • для всех страниц, кроме главной и страниц пагинаций, в конце добавляется информация из поля «Настройки->Общие->Краткое описание»
Добавляем мета тег canonical к каждой странице сайта на WordPress без плагинов

Всем привет! Чтобы добавить запись типа meta rel="canonical" href="url" к каждой странице вашего сайта на WordPress, добавьте этот код в functions.php вашей темы:

function remove_args($url) {
  $parsed = parse_url($url);
 
  $fragment = '';
 
  if (array_key_exists('fragment', $parsed)) {
    $fragment = '#' . $parsed['fragment'];
  }
 
  return sprintf("%s://%s%s%s",
    $parsed['scheme'],
    $parsed['host'],
    $parsed['path'] ?? '',
    $fragment);
}
 
 
function print_canonical_link() {
  $url = "";
 
  // Одиночная страница
  if (is_single()) {
    global $page;
    // Пост из нескольких частей
    if ($page) {
      $url = get_pagenum_link($page);
    }
    else {
      $url = get_permalink();
    }
  }
  // Страница пагинации типа что-то-там/page/N
  else if (is_paged()) {
    $url = get_pagenum_link(get_query_var('paged'));
  }
  // Главная страница сайта
  else if(is_front_page()) {
    $url = get_home_url();
  }
  // Страницы категории или тега
  else if(is_category() || is_tag()) {
    $url = get_term_link(get_queried_object());
  }
 
  if ($url) {
    echo '<link rel="canonical" href="'.remove_args($url).'" />';
  }
}
add_action('wp_head', 'print_canonical_link');

Подробности для непосвящённых: функция print_canonical_link() выводит запись вида
<meta rel="canonical" href="url" /> во время вызова штатной функции wp_head(), что очень уважают поисковые системы, но это неточно. А функция remove_args() удаляет GET аргументы вида «?key=value» из URL. Критика, замечания, пожелания приветствуются.

Загрузка разных счётчиков с помощью jQuery.getScript()

Всем привет! Буду краток:

jQuery(document).ready(function($) {
    $.ajaxSetup({cache : true});
 
    // Данные для Google Analytics
    window.dataLayer = [];
    window.gtag = function() {
        window.dataLayer.push(arguments);
    }
 
    $.getScript(
        'https://www.googletagmanager.com/gtag/js?id=G-41BWRDZLG5',
        function() {
            gtag('js', new Date());
            gtag('config', 'G-41BWRDZLG5');
        }
    );
 
    // Данные для Яндекс.Метрики
    window.ym = function() { (window.ym.a||[]).push(arguments); }
    window.ym.l = 1*new Date();
 
    $.getScript(
        'https://mc.yandex.ru/metrika/tag.js',
        function() {
            ym(91531653, "init", {
                    webvisor:true,
                    trackLinks:true,
                    clickmap:true,
                    accurateTrackBounce:false
                }
            );
        }
    );
 
    // Данные для top.mail.ru
    var _tmr = window._tmr || (window._tmr = []);
    _tmr.push({
        id: "2601331",
        type: "pageView",
        start: (new Date()).getTime()
    });
 
    $.getScript('//top-fwz1.mail.ru/js/code.js');
});

Не забудьте поменять идентификаторы счётчиков!

Обновление скрипта резервного копирования

Обновил скрипт для резервного копирования. Убрал вызов bc, вынес всё в отдельные функции, причесал код, чтобы ShellCheck был счастлив:

#!/usr/local/bin/bash
 
BACKUP_ROOT=/var/backups/manual/
BACKUP_DIR="$BACKUP_ROOT"$(date +"%Y-%m-%d/%H-%M")
PREFIX=$(date +"%Y%m%d_%H%M")
LIMIT=$((4*1024*1024))
 
exit_on_error() {
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
        >&2 echo -e "FAIL"
        exit $exit_code
    fi
}
 
print_used_space() {
    printf "Used space: "
    SIZE=$(du -sB 1 $BACKUP_ROOT | cut -f 1)
    printf "%sMb(%s%%)\n" "$((SIZE / 1024))" "$((SIZE * 100 / LIMIT))"
}
 
backup_etc() {
    FILENAME="$PREFIX"_etc.tar.bz2
    printf "Creating %s .. " "$FILENAME"
    if /usr/bin/tar -Pjcf "$BACKUP_DIR"/"$FILENAME" /etc /usr/local/etc /home /var/db/ports /var/named/etc/namedb /root/scripts > /dev/null 2>&1; then
        printf "OK\n"
    else
        exit_on_error
    fi
}
 
backup_site() {
    FILENAME="$PREFIX"_www.tar.bz2
    printf "Creating %s .. " "$FILENAME"
    if /usr/bin/tar -Pjcf "$BACKUP_DIR"/"$FILENAME" /usr/local/www > /dev/null; then
        printf "OK\n"
    else
        exit_on_error
    fi
}
 
backup_db() {
    FILENAME="$PREFIX"_db.sql.bz2
    printf "Creating %s .. " "$FILENAME"
    if /usr/local/bin/mysqldump --login-path=backup --opt --all-databases --triggers --routines --events | bzip2 -c > "$BACKUP_DIR"/"$FILENAME"; then
        printf "OK\n"
    else
        exit_on_error
    fi
}
 
remove_old_files() {
    removed=0
    for days in $(seq 100 -1 0)
    do
        SIZE=$(du -sB 1 $BACKUP_ROOT | cut -f 1)
        if [[ $SIZE -le $LIMIT ]]; then
            break
        fi
        if [[ -z "$(find $BACKUP_ROOT -type f -mtime +"$days")" ]]; then
            continue
        fi
        printf "Removing files older than %d days:\n" "$days"
        find $BACKUP_ROOT -type f -mtime +"$days"d -delete -print
        find $BACKUP_ROOT -empty -type d -delete -print
        removed=1
    done
 
    if [ $removed -ne 0 ]; then
        true
        return
    fi
 
    false
}
 
if [ ! -d "$BACKUP_DIR" ]; then
        mkdir -p "$BACKUP_DIR"
fi
 
backup_etc
backup_site
backup_db
print_used_space
remove_old_files && print_used_space
true
Краткая инструкция по обновлению порта для сопровождающих

Примерно с 2008 года совершенно случайно являюсь сопровождающим порта sysutils/archivemount в ОС FreeBSD и недавно стал получать сообщения от их багтрекера. Их Bugzilla с упорством достойным поощрения настойчиво раз в неделю присылала мне письма об ошибках. Так что ничего не оставалось делать, как обновить соответствующий порт и в результате родилась эта инструкция.

# Делаем копию оригинала
cp -r /usr/ports/sysutils/archivemount/ /usr/ports/sysutils/archivemount.bak
# Обновляем Makefile (PORTVERSION=new_version, PORTREVISION=0)
vim /usr/ports/sysutils/archivemount/Makefile
# Обновляем файл distinfo командой make makesum
cd /usr/ports/sysutils/archivemount &amp;&amp; make makesum
# Генерируем diff (рекомендуется использовать git diff)
diff -ruN /usr/ports/sysutils/archivemount.bak /usr/ports/sysutils/archivemount &gt; archivemount.diff

Заливаем этот diff через форму багтрекера с припиской в начале [maintainer update]. В качестве примера можно посмотреть обновление archivemount. Также приложите CHANGELOG со списком изменений и, разумеется, проверьте работу порта и новой версии приложения перед отправкой.
Что ещё почитать:
* FreeBSD Porters Handbook
* Руководство FreeBSD по созданию портов

Блог Евгения Жирнова