The Ultimate Guide to Auto-Insert Internal Links in WordPress

Discover the ultimate guide to automatic internal linking in WordPress. Elevate your website's SEO and user experience with our Auto Internal Link WordPress Function.

Written By HarsH

14 min


WordPress dashboard on a computer screen with auto-insert internal links feature

Internal linking is a vital aspect of SEO that helps search engines understand the structure and hierarchy of your website. It also enhances user experience by providing easy navigation to related content. But manually adding internal links can be time-consuming, especially for large websites.

In this blog post, we’ll explore a powerful solution to automate internal link building in WordPress using PHP function. Buckle up as we dive into the code!

The Importance of Internal Linking in SEO

In the ever-evolving landscape of SEO, internal linking remains a cornerstone. It’s not just about connecting your web pages; it’s about building a spider web of relevancy that search engines love.

  • Internal links act as pathways for search engine crawlers, helping them index your site’s content more efficiently.
  • Well-placed internal links guide your visitors through a journey, increasing page views and reducing bounce rates.
  • Internal links distribute page authority throughout your site, boosting the SEO value of individual pages.
  • Consistent, error-free internal linking can lead to improved Google rankings.

Why You Should Automate Internal Linking

Manually adding internal links is like playing chess with your content—strategic but time-consuming. And let’s not forget the risk of human error. Imagine a tool that automatically inserts internal links in your WordPress posts based on predefined keywords. That’s what my auto-insert internal link WordPress function does.

  • Automating internal linking saves you countless hours, freeing you to focus on creating quality content.
  • An automated system ensures that your linking strategy remains consistent across all posts and pages.
  • Automated internal linking minimizes the risk of broken links, a common issue with manual linking.

Why Use This PHP Function Instead of WordPress Internal Linking Plugin?

When searching for the best WordPress plugin for internal linking, you might have came across Link Whisper, Interlinks manager, Internal Link Juicer etc. but when it comes to enhancing the SEO and user experience of your WordPress site, choosing a custom standalone function for internal linking over a standard WordPress plugin offers several compelling advantages.

  1. Enhanced Performance: Standalone functions typically have a smaller footprint than plugins, reducing the risk of website bloat and ensuring faster page load times, which is crucial for SEO and user experience.
  2. Reduced Plugin Conflicts: By using a custom function, you minimize the risk of conflicts with other plugins, leading to a more stable and reliable WordPress environment.
  3. Greater Control and Flexibility: Custom functions allow for more control over the internal linking process, enabling you to fine-tune the logic and adapt to changes in your SEO strategy or website structure.
  4. Focused Functionality: Unlike plugins that may include unnecessary features, a custom function focuses solely on internal linking, making it more efficient and easier to manage.
  5. Scalability and Customization: As your website grows, a custom function can be easily modified and scaled to meet evolving requirements, something that is often limited in pre-built plugins.
  6. Direct Support and Development: Any issues or required enhancements with a custom function can be addressed directly, without relying on external plugin developers for updates or bug fixes.
  7. Cost-Effectiveness: While some plugins come with a subscription fee, a custom function is a one-time development effort that can be more cost-effective in the long run, especially for complex or large-scale websites.

Part 1: The Initial Function

The initial version of the function parsed the content, identified the keywords, and replaced them with appropriate links. This automation significantly reduced the manual effort required in internal linking.

Part 2: Refining the Function

We soon realized that, if the keyword was present twice in the content, the function would correspondingly insert the internal link twice. If the keyword already had a link then the function would replace that link. Also it added links to headings, which was not always desirable. To address these issues, we refined the function.

The code underwent modifications to address these problems. The following adjustments were implemented to remedy the situation:

  1. Implement a verification process to ascertain if a keyword is already encompassed within an anchor tag (<a>). In cases where it is, the function will refrain from substituting that specific keyword.
  2. The array $used_keywords is utilized to monitor whether a keyword has been hyperlinked previously. When a keyword undergoes hyperlinking initially, it gets recorded in this array. If the same keyword reappears, it will be overlooked due to the conditional check if (!isset($used_keywords[$keyword])). This guarantees the singular linking of each keyword throughout the content.
  3. Engage in the use of regular expressions combined with DOMDocument manipulation to ensure that link insertion is confined to text present solely within paragraphs.

Part 3: Enhancing Performance and Usability

  1. Keyword Limitation

To further enhance the function’s performance, we introduced the concept of keyword limitation. This meant processing only a set number of keywords per execution, reducing the load on the server.

  1. Batch Processing

We then stepped up the function’s capability by implementing batch processing. This allowed the function to handle keywords in batches over multiple page loads, ensuring efficiency for sites with a large number of keywords.

Part 4: Scheduling with WP-Cron

Handling such tasks in real-time can be resource-intensive. Therefore, we introduced scheduling to manage this process more effectively.

WP-Cron is WordPress’s scheduling system that allows for the execution of scheduled tasks. We utilized WP-Cron to trigger our batch processing function at specific intervals.

Our function was integrated with WP-Cron, setting it to run every 10 hours. This ensured that the batch processing was carried out regularly, without overloading the server.

We set up a custom interval of 10 hours, aligning with the site’s traffic and content update frequency. This interval was chosen to balance the load and ensure timely processing of new keywords.

Part 5: Bringing It All Together

The final function combined internal linking, exclusion of headings, keyword limitation, batch processing, and WP-Cron scheduling into a cohesive and efficient tool.

Here’s a step-by-step guide to implement this PHP function:

Step 1: Create a new page for Keywords and URLs

  • Create a new page in WordPress by going to ‘Pages’ and selecting ‘Add New’.
  • Title this page appropriately, such as “Keywords and URLs.”
  • In the content area, list your keywords and corresponding URLs, each on a new line, separated by a comma. For example:

Note: If you are using WordPress Blocks, then you will have to select classic block and add the Keywords & URLs or else it won’t work.

Once you add, note down the Page ID. You can typically find the page ID in the URL while editing the page, looking something like post=123. And you don’t need to publish this page.

Step 2: Install and Activate the WP Code Plugin

  • Log in to your WordPress admin dashboard.
  • Navigate to Plugins > Add New.
  • In the search bar, type “WPCode” and install.
  • Go to the WP Code plugin in your WordPress dashboard.
  • Create a new snippet by clicking ‘Add New’.
  • Title the snippet for your reference, such as “Internal Linking Function.”
  • In the code area, paste the full PHP code.
 * Auto Add Internal Link Function by PBT
function process_keywords_batch() {
    $page_id = 123; // Replace 123 with your actual page ID
    $max_keywords = 10; // Max number of keywords to process per batch
    $last_index = get_option('last_processed_keyword_index', 0);

    // Fetch the keywords content
    $keywords_content = get_post_field('post_content', $page_id);
    if (empty($keywords_content)) {
        error_log("No content found for page ID: " . $page_id);

    $lines = explode("\n", $keywords_content);
    $keywords = array();

    // Process each line and limit the number of keywords per batch
    foreach ($lines as $index => $line) {
        if ($index < $last_index || empty($line)) continue;
        if (count($keywords) >= $max_keywords) break;

        $parts = explode(',', $line, 2);
        if (count($parts) < 2) {
            error_log("Invalid line format: " . $line);

        list($keyword, $url) = array_map('trim', $parts);
        $keywords[$keyword] = $url;

    // Store only the keywords and URLs in the transient
    set_transient('processed_keywords_links', $keywords, 4 * DAY_IN_SECONDS);

    // Update the index for the next batch
    update_option('last_processed_keyword_index', $index + 1);
function display_processed_content($content) {
    // Get the processed keywords and their links
    $keywords_links = get_transient('processed_keywords_links');
    if ($keywords_links === false) {
        return $content; // No processed data, return original content

    foreach ($keywords_links as $keyword => $url) {
        if (preg_match('/<a [^>]*>[^<]*' . preg_quote($keyword, '/') . '[^<]*<\/a>/', $content)) {
            continue; // Skip if the keyword is already part of a link
        $link = '<a href="' . esc_url($url) . '">' . esc_html($keyword) . '</a>';
        $content = preg_replace('/\b' . preg_quote($keyword, '/') . '\b/', $link, $content, 1);

    return $content;

add_filter('the_content', 'display_processed_content');

// Custom Cron Schedule
function custom_cron_schedule($schedules) {
    $schedules['every_ten_hours'] = array(
        'interval' => 36000, // 10 hours in seconds
        'display'  => __( 'Every Ten Hours' )
    return $schedules;
add_filter('cron_schedules', 'custom_cron_schedule');

// Hook the function to the custom action
add_action('process_keywords_batch_event', 'process_keywords_batch');

// Schedule the Cron Event on Theme Setup
function schedule_keywords_batch_on_theme_setup() {
    if (!wp_next_scheduled('process_keywords_batch_event')) {
        wp_schedule_event(time(), 'every_ten_hours', 'process_keywords_batch_event');
add_action('after_setup_theme', 'schedule_keywords_batch_on_theme_setup');

// Clear the scheduled event on theme switch
function clear_scheduled_keywords_batch() {
add_action('switch_theme', 'clear_scheduled_keywords_batch');
  • Update the $page_id variable in the function with the ID of the page you just created. For example:
$page_id = 123; // Replace 123 with your actual page ID
  • And Finally, activate the snippet.
Managing the WP-Cron for Automated Batch Processing

The advanced feature of our custom function is its ability to process keywords in batches using WordPress’s built-in scheduling system, WP-Cron. This ensures that the function runs efficiently and doesn’t overload your server, especially useful for websites with a large number of keywords.

Understanding WP-Cron Scheduling

WP-Cron is a system within WordPress that simulates a cron job, commonly used in Unix systems. Unlike a real cron job that runs at specific times set on the server, WP-Cron triggers tasks based on website traffic. Specifically, scheduled tasks are checked and executed whenever someone visits your website.

Setting Up the Script’s Schedule

In our function, WP-Cron is set to run the keyword processing script every 10 hours. This interval was chosen to balance server load and the frequency of content updates. Here’s how this works:

Automated Scheduling: When you activate the snippet containing our function, it automatically schedules the keyword processing task using WP-Cron.

Running the Task: Every 10 hours, the WP-Cron system checks if it’s time to run the task. If so, and there’s a visit to your website around that time, the task will execute, processing the next batch of keywords.

Efficient Processing: By processing keywords in batches and scheduling the task, we ensure that the server is not overwhelmed, especially important for sites with a substantial amount of content.

Monitoring and Troubleshooting

WP Crontrol Plugin: To monitor and manage WP-Cron events, you can use a plugin like WP Crontrol. It allows you to view and control scheduled tasks, including our keyword processing task.

Manual Trigger: If you need to process keywords immediately or outside the scheduled times, you can manually trigger the batch processing function via WP Crontrol.

Handling Low Traffic: If your website has low traffic, WP-Cron events might not trigger precisely on schedule. In such cases, you may consider using a real cron job via your hosting service for more accurate scheduling.

Resets Batch Processing Index

The “Reset Batch Index” script is designed to reset the index used for batch processing in your internal linking function. This script is particularly useful in scenarios where the automated batch processing of internal links encounters issues or inconsistencies, such as failing to add links to new content.

The script sets the last_processed_keyword_index option back to 0. This index is used by your batch processing function to keep track of which keywords have been processed. Resetting it ensures that the batch processing starts over from the beginning.

When and How to Use this script?

  • Stalled Batch Processing: If you notice that new keywords aren’t being processed, it could be due to the batch processing index reaching a state where it doesn’t recognize new additions.
  • After Adding New Keywords: When you significantly update or add a new batch of keywords and URLs, resetting the index ensures that these additions are processed in the next batch.

How to Activate?

  • Go to the WP Code plugin in your WordPress dashboard.
  • Create a new snippet by clicking ‘Add New’.
  • Title the snippet for your reference, such as “Reset Batch Processing Index For Auto Internal Linking”
  • In the code area, paste the full PHP code.
 * Reset Batch Index By PBT

add_action('admin_init', function() {
    update_option('last_processed_keyword_index', 0);
  • And activate the snippet once and then deactivate it.

It’s best used periodically or in specific situations where you need to ensure all keywords, especially newly added ones, are processed. Consider deactivating the plugin once the index has been reset to avoid unnecessary resets on subsequent admin page loads.

This function serves as a handy tool for managing and maintaining the efficiency of your internal link batch processing system, ensuring that all keywords, new and old, are consistently processed.

Alternate Auto Add Internal Link Function ( Easy)

In case you encounter issues with the prior script or face challenges in its implementation, consider using this alternative Auto Add Internal Link Function as a solution.

The only major difference lies in performance efficiency. Unlike the previous script, this one does not utilize WP Cron for scheduling the internal linking function. Instead, it processes the keywords immediately upon their addition.

The setup process remains identical. Simply replace the previous code with this new script.

 * Auto Add Internal Link Function by PBT
function auto_insert_internal_links($content) {
    // ID of the page/post containing keywords and URLs
    $page_id = 123;  // Replace 123 with your actual page ID

    // Fetch the content of the page/post
    $keywords_content = get_post_field('post_content', $page_id);

    // Check if content is fetched
    if (empty($keywords_content)) {
        error_log("No content found for page ID: " . $page_id);
        return $content;

    // Split content into lines
    $lines = explode("\n", $keywords_content);
    $keywords = array();

    // Process each line
    foreach ($lines as $line) {
        // Skip empty lines
        if (empty($line)) continue;

        // Split line into keyword and URL
        $parts = array_map('trim', explode(',', $line, 2));

        // Check if line has two parts
        if (count($parts) < 2) {
            error_log("Invalid line format: " . $line);

        list($keyword, $url) = $parts;
        $keywords[$keyword] = $url;

    // Function to replace keywords with links in a piece of text
    $replace_keywords_in_text = function ($text) use ($keywords) {
        foreach ($keywords as $keyword => $url) {
            // Skip if the keyword is already part of a link
            if (preg_match('/<a [^>]*>[^<]*' . preg_quote($keyword, '/') . '[^<]*<\/a>/', $text)) {

            // Create the link HTML
            $link = '<a href="' . esc_url($url) . '">' . esc_html($keyword) . '</a>';
            // Replace the first occurrence of the keyword with the link in the text
            $text = preg_replace('/\b' . preg_quote($keyword, '/') . '\b/', $link, $text, 1);
        return $text;

// Optimized regex for matching paragraphs
    $content = preg_replace_callback(
        function ($matches) use ($replace_keywords_in_text) {
            return '<p>' . $replace_keywords_in_text($matches[1]) . '</p>';

    return $content;

// Hook the function to 'the_content' filter
add_filter('the_content', 'auto_insert_internal_links');

The auto-insert internal link PHP code is a powerful asset for any WordPress site owner or developer looking to streamline their SEO efforts. By automating internal linking, offering flexibility, optimizing performance, and providing easy integration with WordPress, this solution is a game-changer in the world of SEO.

Investing in automation and leveraging this PHP code can elevate your SEO strategy, enhance user experience, and contribute to the overall success of your online presence. It’s time to embrace the future of SEO with automation!

Have you embarked on a similar journey in WordPress development? Share your experiences or queries about this function. Let’s continue to innovate and enhance our WordPress sites together!

About the author


Leave a Comment