I recently wanted to add a post view count feature to my blog. I needed to backfill historical view counts for old posts, enable automatic counting for new visits, and do all of this without modifying the theme’s core code or relying on complex operations. After much trial and error, I successfully met these requirements. I have documented the complete process, the issues I encountered, and their solutions below for fellow bloggers with the same needs.
1. Background and Requirements
My blog is built on WordPress, and I track historical access data for all past posts through Nginx logs. The format is as follows (visit count on the left, post URL on the right):
75 /2026/03/02/9330/
26 /2018/04/04/2559/
25 /2018/04/13/2597/
25 /2018/04/09/2576/
24 /2018/04/03/2530/
20 /2022/02/23/6014/
12 /2026/04/14/9496/
11 /2024/08/16/8771/
9 /2022/06/30/6720/
9 /2020/11/03/4593/Core requirements:
- Batch import historical view counts from Nginx logs into WordPress
- Automatically increment view counts for subsequent organic visitor visits
- Implement this via a plugin without modifying the theme’s functions.php
- Display in Chinese on the front end (e.g., “阅读:75 次”), and move the position from the footer to the header
2. Tool Selection: Post Views Counter Plugin
After comparing several view tracking plugins, I chose Post Views Counter (official description: “allows you to collect and display how many times a post, page, or other content has been viewed in a simple, fast and reliable way”) for the following reasons:
- Free, stable, and supports bulk import of historical data
- Customizable display styles and positions without modifying the theme’s core code
- Automatically tracks subsequent visits and supports setting a counting interval to prevent inflated data
Installation method: WordPress Dashboard → Plugins → Add New → Search for “Post Views Counter” → Install and Activate.
3. Core Operation: Importing Historical View Counts from Nginx Logs
This is the most critical step and the most prone to pitfalls. No log format conversion is needed throughout the process. First, extract data from the Nginx logs to generate views.txt, then perform the import based on that file.
3.1 Generating the views.txt File from Nginx Logs
The default storage path for Nginx logs is usually /var/log/nginx/access.log (this may vary slightly depending on the server; you can check it using tools like the BT Panel or Xshell). We need to extract the blog post access records from the logs, count the visits for each post, and ultimately generate the views.txt file.
3.1.1 Prerequisites
The blog post URL format is /year/month/day/post-ID/ (e.g., /2026/03/02/9330/). The Nginx logs record every visit to URLs matching this format. We will filter and count these visits using the command line.
3.1.2 Specific Steps (Direct Server Operation, Concise Version)
- Connect to the server: Remotely connect to the server via Alibaba Cloud Workbench and log in with your credentials. After logging in, execute the following command to copy the Nginx log to the WordPress root directory:
cd /data/wwwroot/www.shuijingwanwq.com/
cp /data/wwwlogs/www.shuijingwanwq.com_nginx.log /data/wwwroot/www.shuijingwanwq.com/- Filter post access records and count visits: Execute the following command to automatically filter records matching the blog post URL format, count the visits for each post, and output the results to the views.txt file:
# Filter records with the URL format /year/month/day/post-ID/, count visits, and generate views.txt
grep -E 'GET /[0-9]{4}/[0-9]{2}/[0-9]{2}/[0-9]+/ HTTP' www.shuijingwanwq.com_nginx.log | awk '{print $7}' | sort | uniq -c | sort -nr > views.txt- Once the command finishes executing, views.txt will be automatically generated in the WordPress root directory. The format is “visit count + post URL” and requires no manual adjustment. An example is shown below:
75 /2026/03/02/9330/
26 /2018/04/04/2559/
25 /2018/04/13/2597/
Additional Notes
- If you have multiple log files (e.g., daily split logs like access.log-20260414), you can use the cat access.log* command to merge all logs before filtering;
- If your blog post URL format is different (e.g., no date prefix), you need to modify the regular expression in the command (replace /[0-9]{4}/[0-9]{2}/[0-9]{2}/[0-9]+/ with your own blog’s URL format);
- Windows servers: You can open the Nginx logs using Notepad++, use the “Find and Replace” feature to filter URLs, and then manually count the visits, or use PowerShell to execute similar filtering commands.
3.2 Preparation
- Upload the views.txt file generated in the previous step to the WordPress root directory (the same directory as wp-config.php);
- Create a new PHP script (named make_sql.php) to read views.txt and generate a directly importable SQL file. The code is as follows (copy directly without modification):
<?php
require_once('./wp-config.php');
$lines = file('views.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$sql_lines = [];
foreach ($lines as $line) {
$line = trim($line);
// 匹配 访问次数 + 文章URL
if (preg_match('/(\d+)\s+(\/.*\/)/', $line, $m)) {
$count = intval($m[1]);
$url = $m[2];
// 根据URL获取文章ID
$post_id = url_to_postid($url);
if ($post_id) {
// 直接使用日志原始数据,不打折(避免少量访问文章数据失真)
$final = $count;
// 关键:插件真正读取的type=4(文章类型),period=total(总浏览量)
$sql_lines[] = "($post_id, 4, 'total', $final)";
}
}
}
if (!empty($sql_lines)) {
$sql = "REPLACE INTO wp_post_views (id, type, period, count) VALUES\n";
$sql .= implode(",\n", $sql_lines);
$sql .= ";";
// 生成SQL文件
file_put_contents('views_import.sql', $sql);
echo "✅ SQL已生成(适配Post Views Counter插件)";
echo "<a href='views_import.sql' target='_blank'>下载views_import.sql</a>";
} else {
echo "❌ 未匹配到有效文章数据";
}
3.3 Generating and Importing the SQL
- Access the script URL in your browser: https://www.shuijingwanwq.com/make_sql.php. This will automatically generate the views_import.sql file. Download this file;
- Go to Alibaba Cloud’s DMS, locate your WordPress database, open a new SQL window, paste the contents of views_import.sql, and execute the import; see Figure 2

- Clean up erroneous junk data (due to early pitfalls, invalid data with type=1 may have been generated) by executing the following SQL:
DELETE FROM wp_post_views WHERE type = 1 AND period = 'total';4. Common Issue Troubleshooting (Must Read!)
After importing the data, you might encounter issues with incorrect view count displays. Below are the pitfalls I encountered and their solutions to save you debugging time.
Issue 1: After import, the page displays the view count as 1 instead of 75 from the logs
Cause: The plugin has two data storage locations. It prioritizes reading the _post_views_count cache value in the wp_postmeta table instead of the actual data in the wp_post_views statistics table. Additionally, the early incorrect import used type=1 (which the plugin does not recognize); the plugin’s default counts are stored under type=4.
Solution:
- Execute SQL to clear the cache: DELETE FROM wp_postmeta WHERE meta_key = ‘_post_views_count’;
- Ensure the imported SQL uses type=4 (the post type recognized by the plugin), then re-execute the import SQL.
Issue 2: Multiple records for the same post appear in the wp_post_views table
Cause: The plugin automatically tracks daily, monthly, and yearly view counts (type=0 for daily, type=2 for monthly, type=3 for yearly). This is normal; you just need to ensure that the record with type=4 and period=total contains the correct historical data.
Solution: No need to delete records of other types. Just clean up the invalid type=1 data (as shown in step 3.2), which will not affect the plugin’s normal counting.
Issue 3: After clearing the cache, the view count still does not display the correct value
Cause: The imported SQL has the wrong type (e.g., type=1). The plugin defaults to reading the total record with type=4.
Solution: Re-execute the correct import SQL (type=4). There is no need to clear the cache again; simply refresh the page to display the correct data.
5. Subsequent Optimization: Display Settings and Counting Intervals
After importing the historical data, simple settings are needed to make the view count display more suitable for a Chinese blog style and to make the statistics more accurate.
5.1 Custom Chinese Display (Replacing “Post Views: “)
- Go to WordPress Dashboard → Post Views → Settings → Display;
- Find the “Display” → Views Label option, and change the default “Post Views: ” to Chinese. Recommended options:
- Concise version: 阅读:
- Full version: 浏览量:
- After saving the settings, the front end will display “浏览量:75 次”, which fits Chinese reading habits.
5.2 Adjusting the View Count Display Position (From Footer to Header)
The plugin has a built-in display position setting (Display Targets) that requires no complex operations. Using the plugin’s built-in feature to adjust this is highly recommended. Details: The core function of Display Targets is to “choose where the counter is inserted and which content types it attaches to” (official description: Choose where the counter is inserted and which content types it attaches to). The default insertion position is “After the content” (i.e., the footer). We just need to change it to “Before the content” (i.e., the header) to quickly adjust the position without modifying code. See Figure 3

- Go to WordPress Dashboard → Post Views → Settings → Display;
- Find the “Display Targets” option (corresponding to position settings);
- In the “Position” dropdown menu, select “Before the content”;
- After saving the settings, the view count will automatically appear at the beginning of the post content (header) without any extra steps.
Additional Notes: This setting applies synchronously to all posts without needing per-post adjustments. You can also select the associated content types in Display Targets (e.g., apply only to posts, not pages) to suit your blog’s operational needs.
5.3 Setting the Counting Interval (Preventing Inflated Data)
The plugin’s default counting interval is 24 hours (multiple visits by the same visitor within a day count as only 1). You can adjust this based on your blog’s visitor traffic:
- Go to Post Views → Settings → Counting, and find “Counting Interval” (unit: hours);
- Recommended setting: 1 hour (enter 1). Reasons:
- Prevents duplicate counting from the same visitor refreshing the page in a short period, making the data more realistic;
- Visiting again after 1 hour will count normally, without missing valid visits;
- If you prefer maximum tracking sensitivity (counting every visit), you can set it to 0 (not recommended, as it easily leads to inflated data).
6. Final Results and Summary
After completing the above operations, your blog’s view counts will achieve the following:
- Historical data: Batch imported from Nginx logs, accurately displaying past visit counts for each post;
- Automatic counting: View counts automatically increment for subsequent visitor visits without manual intervention;
- Display effect: Chinese style (浏览量:75 次), positioned at the post header, concise and aesthetically pleasing;
- Clean data: No junk data, accurate statistics, and no regular maintenance required.
The core of this entire process is correctly identifying the Post Views Counter plugin’s data storage rules (type=4, period=total) and avoiding the pitfalls related to caching and data types. It requires no modification to the theme’s core code, making it suitable for all non-technical bloggers to operate. If your blog also needs to backfill historical view counts, you can follow the process in this article directly. If you have any questions, feel free to leave a comment for discussion.
