Opens in a new tab
  1. Home
  2. Guides
  3. Content
Content guide

WordPress Self-Pingbacks Explained

Learn how WordPress self-pingbacks are created when posts link to other content on the same site, how the pingback pipeline, pre_ping and XML-RPC are involved, why self-pings can clutter discussion workflows and how to disable them without removing internal links.

  • Updated September 23, 2026
  • 25 min read
  • WordPress guide

WordPress self-pingbacks are automated pingback notifications that can be created when one post on your website links to another post on the same WordPress installation.

For example:

Post A
↓
links to
↓
Post B
on the same website

The internal link itself is useful.

But WordPress can also process that URL through its pingback system, effectively causing the website to notify itself that one of its own posts linked to another.

The result can appear in WordPress as a comment-like pingback entry on the destination post.

This is called a:

self-pingback
or
self-ping

Self-pingbacks are not the same thing as internal links.

They are also not the same as:

  • normal comments;
  • trackbacks;
  • external pingbacks;
  • XML-RPC as a whole;
  • REST API requests.

The useful mental model is:

Internal link
→ part of your content

Pingback
→ automated notification about a link

Self-pingback
→ that notification happens between URLs
   on your own site

This guide explains how WordPress self-pingbacks work, when they are created, how WordPress discovers pingback endpoints, how they interact with XML-RPC and Discussion Settings, why they can become administrative noise and how to stop them without removing your internal links or unnecessarily disabling unrelated functionality.

Quick answer

A self-pingback can happen when:

Post A contains a full URL
pointing to Post B
on the same WordPress site

+

outgoing pingbacks are enabled

+

WordPress processes the link

+

the destination can receive pingbacks

The resulting notification may be stored on Post B as a pingback-style comment.

If you want to keep internal links but prevent only the self-pingback process, WordPress provides:

pre_ping

which runs before WordPress processes outgoing pingback destinations.

A typical solution removes same-site URLs from that queue:

function project_disable_self_pingbacks(
    &$post_links
) {

    $home_url =
        home_url( '/' );

    foreach (
        $post_links as $key => $link
    ) {

        if (
            str_starts_with(
                $link,
                $home_url
            )
        ) {
            unset(
                $post_links[ $key ]
            );
        }
    }
}

add_action(
    'pre_ping',
    'project_disable_self_pingbacks'
);

This preserves:

internal hyperlink
→ yes

self-pingback
→ no

external pingbacks
→ still possible

XML-RPC
→ unchanged

The complete implementation strategy is covered in Disable Self-Pingbacks Without Disabling XML-RPC.

What is a pingback?

A pingback is an automated notification sent between websites when one page links to another page and both sides support the pingback mechanism.

The official WordPress Trackbacks and Pingbacks documentation describes pingbacks as automated link notifications that can appear in the receiving site’s comments system.

Basic external pingback example

Suppose:

site-a.com/article/
↓
contains a link to
↓
site-b.com/guide/

If pingbacks are enabled and supported:

Site A
↓
detects the link

↓
discovers Site B's
pingback endpoint

↓
sends pingback.ping

↓
Site B verifies the source

↓
Site B may store
a pingback comment

What makes a pingback a self-pingback?

The process becomes a self-pingback when both URLs belong to the same site.

For example:

https://example.com/wordpress-security/

links to

https://example.com/wordpress-backups/

The source and destination are both:

example.com

so WordPress can end up notifying:

example.com
→ about a link from example.com
→ to example.com

Example of a real self-pingback workflow

Imagine you publish:

How to Secure WordPress

and include:

<a href="https://example.com/wordpress-backups/">
    WordPress backups
</a>

WordPress can process that absolute URL as a pingback destination.

The destination article:

WordPress Backups

may then receive a pingback representing the first article.

In the comments area you might see something conceptually resembling:

Pingback:
How to Secure WordPress

The internal link and the pingback are separate things

This distinction matters more than anything else in this guide.

The internal link exists inside:

post_content

The self-pingback is generated later by WordPress’s publishing and notification workflow.

You can therefore have:

internal link
→ preserved

self-pingback
→ disabled

without weakening your internal linking strategy.

See Pingbacks, Trackbacks & Internal Links for the broader relationship between the three systems.

Why WordPress creates self-pingbacks

WordPress’s pingback system is designed around URLs, not around the editorial intention behind each link.

When WordPress processes a post, Core can extract URLs from its content.

The relevant function is:

pingback()

The official pingback() documentation describes it as the function that pings back links found in a post.

WordPress extracts URLs from the post

Inside the current Core implementation:

wp_extract_urls()

is used to identify URLs present in the post content.

Conceptually:

post_content
↓
wp_extract_urls()
↓
candidate URL list

WordPress removes some obvious non-candidates

Core performs several checks before a URL enters the final ping list.

For example, it avoids:

  • URLs already pinged by the post;
  • a URL resolving to the same post itself;
  • local attachment URLs;
  • certain root-level URLs that do not point to a specific resource.

But another post on the same site can remain eligible

Consider:

Current post ID
→ 100

linked internal post ID
→ 200

The destination is not:

the same post

so it can remain in the outgoing list.

That is how a legitimate internal relationship can become a self-pingback candidate.

WordPress does not automatically remove every same-site URL

Core prevents a post from pinging itself directly.

That is different from preventing:

Post A
→ Post B
on the same domain

This is the behavior addressed by self-pingback filtering.

WordPress tracks URLs that have already been pinged

The current Core implementation retrieves:

get_pung()

before processing candidate URLs.

This contains URLs that the post has already successfully pinged.

Why?

Without this record, repeatedly updating the same post could repeatedly notify the same destination.

Conceptually:

new URL
→ eligible

already pinged URL
→ skip

Successful ping destinations are recorded

After a successful pingback, WordPress can use:

add_ping()

to record the destination against the source post.

Self-pingbacks can therefore appear only once for a given source-destination relationship

That can sometimes make the behavior seem inconsistent.

You may update a post and see:

no new self-pingback

simply because WordPress already recorded that destination as pinged earlier.

How publishing triggers pingback processing

WordPress does not need to perform every pingback operation directly inside the main post-save request.

Core’s publishing workflow can mark a published post for ping processing and schedule the:

do_pings

event.

When outgoing pingbacks are enabled, WordPress can add:

_pingme

post metadata.

do_all_pingbacks() processes those posts

The official do_all_pingbacks() documentation shows that WordPress:

finds posts with _pingme
↓
removes the marker
↓
calls pingback()

for each one.

This explains why pingback behavior is part of the publishing workflow

The sequence is approximately:

publish post
↓
post marked for ping processing
↓
do_pings event
↓
do_all_pingbacks()
↓
pingback()
↓
extract URLs
↓
filter candidates
↓
pre_ping
↓
discover endpoints
↓
send pingbacks

Where pre_ping fits

The:

pre_ping

action runs after WordPress has built the candidate list but before it starts contacting those destinations.

The official pre_ping documentation states that it fires immediately before pinging back links found in a post.

WordPress passes three values

$post_links
$pung
$post_id

where:

$post_links
→ URLs about to be checked

$pung
→ URLs already pinged

$post_id
→ source post ID

The first two arrays are passed by reference

This allows a plugin to modify them directly.

For self-pingback removal:

$post_links
→ inspect each destination
→ remove local destinations

Why pre_ping is ideal for self-pingbacks

At this point:

  • the internal link is already stored normally;
  • WordPress has already extracted candidate URLs;
  • the pingback has not yet been sent;
  • remote endpoint discovery has not yet completed for the filtered URL.

This gives you a clean interception point.

What happens after pre_ping?

For every URL that remains in the queue, WordPress calls:

discover_pingback_server_uri()

The official discover_pingback_server_uri() documentation describes how WordPress tries to find a pingback server endpoint for the target URL.

WordPress first checks the HTTP headers

The current implementation sends a HEAD request and checks for:

X-Pingback

If necessary, WordPress examines the HTML

If the header does not provide the endpoint, WordPress can fetch the page and look for:

rel="pingback"

inside the document markup.

Example pingback discovery link

<link
    rel="pingback"
    href="https://example.com/xmlrpc.php"
/>

Once discovered, WordPress sends an XML-RPC request

The current Core pingback() implementation creates an XML-RPC client and invokes:

pingback.ping

with:

source URL
+
destination URL

Self-pingback sequence in detail

Post A
https://example.com/post-a/

contains:

https://example.com/post-b/

↓

WordPress extracts URL

↓

post-b remains eligible

↓

pre_ping runs

↓

if no self-ping filter exists,
post-b remains

↓

WordPress requests post-b

↓

discovers pingback endpoint

↓

https://example.com/xmlrpc.php

↓

WordPress sends pingback.ping

↓

source:
https://example.com/post-a/

destination:
https://example.com/post-b/

↓

the same WordPress site
receives the request

↓

destination validates source

↓

pingback may be stored
against Post B

This is why self-pingbacks feel redundant

Your server can effectively perform:

outbound HTTP request
↓
to itself
↓
discover itself
↓
call its own XML-RPC endpoint
↓
verify one of its own pages
↓
store a notification
about its own internal link

There are historical reasons for the generic architecture, but on a modern content-heavy site the result often provides very little editorial value.

How the receiving side works

A pingback is not blindly accepted simply because another site sends:

pingback.ping

The receiving WordPress installation performs validation.

It receives:

source URL
destination URL

and verifies the relationship before registering the notification.

The destination can reject the pingback

Possible reasons include:

  • pingbacks are disabled for the destination;
  • the destination URL is invalid;
  • the source URL cannot be verified;
  • the pingback already exists;
  • the request is blocked by another security or discussion policy.

A self-pingback is still processed as a real pingback

WordPress does not conceptually say:

"This came from myself,
so create a special
self-pingback object."

It goes through the normal pingback architecture with the unusual circumstance that source and destination belong to the same site.

Where self-pingbacks appear in WordPress

Pingbacks are part of WordPress’s discussion system.

They can therefore appear alongside comment-related data in wp-admin.

A typical administration workflow may show:

Comments

John:
Great article

Pingback:
Related WordPress Security Guide

Spam comment:
Buy suspicious things now

because human comments, pingbacks and trackbacks all participate in the broader discussion architecture.

Pingbacks are not normal human comments

A human comment is created by a person submitting a comment form or equivalent interface.

A pingback is generated by site-to-site link notification.

The difference is:

Comment
→ person submits discussion content

Pingback
→ another resource reports a link

WordPress stores them differently by comment type

The database can distinguish:

comment
pingback
trackback

even though they can all appear through related administration interfaces.

Self-pingbacks are not trackbacks

Pingbacks and trackbacks both originated as ways for websites to notify one another about links.

They are not identical.

The official WordPress documentation summarizes the distinction as:

Pingback
→ automatic

Trackback
→ manually initiated legacy notification

Trackbacks can include an excerpt

Traditional trackbacks send information such as:

  • source URL;
  • title;
  • blog name;
  • excerpt.

Pingbacks operate differently

The receiving site verifies the source link rather than trusting an excerpt provided by the sender.

A self-pingback is specifically a pingback phenomenon

When this guide refers to:

self-ping

it means an automated pingback from one URL on your site to another URL on that same site.

Self-pingbacks and XML-RPC

Pingbacks are closely connected to WordPress XML-RPC.

The standard XML-RPC endpoint is:

https://example.com/xmlrpc.php

WordPress exposes pingback XML-RPC methods

These include:

pingback.ping

pingback.extensions.getPingbacks

through the XML-RPC server.

This does not mean XML-RPC and self-pingbacks are the same setting

They are different layers.

XML-RPC
→ remote communication interface

pingback.ping
→ one XML-RPC method

self-pingback
→ one specific scenario
   involving the pingback system

You can disable self-pingbacks without disabling XML-RPC

Filtering:

pre_ping

does not make:

/xmlrpc.php

unavailable.

It only changes which outgoing URLs reach the later pingback stages.

See Disable Self-Pingbacks Without Disabling XML-RPC for the implementation.

Do not misunderstand xmlrpc_enabled

A very common snippet is:

add_filter(
    'xmlrpc_enabled',
    '__return_false'
);

It is frequently described as:

disable all XML-RPC

but that description is incomplete.

The official xmlrpc_enabled documentation states that it controls XML-RPC methods requiring authentication.

It specifically does not automatically disable:

pingbacks
and
other unauthenticated custom endpoints

This matters when diagnosing self-pingbacks

If somebody adds:

xmlrpc_enabled = false

and expects:

all pingback behavior
→ gone

that assumption is unreliable.

XML-RPC method control is separate again

WordPress provides:

xmlrpc_methods

for modifying the methods exposed by the XML-RPC server.

The official xmlrpc_methods documentation says that built-in methods can be removed from the registered method array.

Example

function project_remove_pingback_methods(
    $methods
) {

    unset(
        $methods['pingback.ping']
    );

    unset(
        $methods[
            'pingback.extensions.getPingbacks'
        ]
    );

    return $methods;
}

add_filter(
    'xmlrpc_methods',
    'project_remove_pingback_methods'
);

But that addresses a different requirement

Compare:

pre_ping
→ outgoing destination filtering

xmlrpc_methods
→ XML-RPC method availability

Keep the policies separate

A site might reasonably use:

self-pingbacks
→ disabled

external outgoing pingbacks
→ enabled

incoming pingbacks
→ enabled

other XML-RPC methods
→ enabled

or:

self-pingbacks
→ disabled

all pingbacks
→ disabled

XML-RPC publishing
→ still enabled

or:

all XML-RPC
→ blocked

pingback system
→ consequently unavailable

These are separate architectural choices.

For the wider protocol, see XML-RPC in WordPress, Explained.

For security and compatibility considerations, see What Is XML-RPC in WordPress, and Why Disable It?.

Which WordPress settings control pingbacks?

WordPress exposes relevant controls under:

Settings
→ Discussion

The official Discussion Settings documentation separates outgoing notifications from incoming link notifications.

Attempt to notify blogs linked from the article

The setting:

Attempt to notify any blogs
linked to from the article

controls the normal outgoing ping workflow.

If you disable it

You are not specifically saying:

disable self-pingbacks

You are saying more broadly:

do not attempt outgoing
link notifications

That can affect external pingbacks too

For example:

internal URL
→ no ping

external URL
→ no ping

This may be exactly what you want

If the site does not use outgoing pingbacks at all, disabling them broadly can be simpler than selectively filtering local URLs.

But it is different from self-pingback filtering

If you want:

internal URLs
→ no ping

external URLs
→ continue normal ping processing

then:

pre_ping

is a more targeted solution.

Incoming pingbacks have their own setting

WordPress also provides:

Allow link notifications
from other blogs
(pingbacks and trackbacks)

for new content.

This answers another question

Should this website
accept link notifications
from other websites?

It does not directly answer:

Should this website
ping itself?

WordPress discussion settings can be overridden per post

Site-wide Discussion Settings often act as defaults for new content.

Individual posts can have different:

ping_status

values.

This means old posts may behave differently

You can change the global setting today and still have historical content with:

pings = open

because its stored status was created earlier.

See WordPress Per-Post vs. Site-Wide Comment Settings.

Self-pingbacks and internal links

A common mistake is treating the self-pingback as evidence that the internal hyperlink itself is problematic.

It is not.

Internal links are part of normal website architecture

Good internal links can:

  • connect related topics;
  • help readers continue their journey;
  • help crawlers discover pages;
  • establish hierarchy;
  • support topic clusters;
  • provide contextual navigation.

The useful component is the hyperlink

Article about backups
↓
links to
↓
article about migrations

That relationship can be editorially valuable.

The self-pingback is optional metadata

The site does not need a second comment-like object merely to remember that the link exists.

Do not remove internal links to prevent self-pingbacks

This would be the wrong tradeoff:

remove useful internal navigation
↓
avoid minor admin notification

Relative URLs can sometimes avoid self-pings

The WordPress user documentation notes that a full absolute URL such as:

https://example.com/article/

can produce a self-ping, while a relative URL such as:

/article/

can avoid it.

Why?

WordPress’s pingback process extracts URLs from content.

A relative path does not look like the same complete remote URL that an absolute internal link does.

But rewriting your link strategy just for pingbacks is not ideal

There are several reasons:

  • editors may normalize links;
  • migration workflows may have specific URL requirements;
  • content can be reused outside the original context;
  • canonical-linking strategy should not be dictated by a legacy notification feature.

Use a pingback-specific solution when possible

Instead of changing:

every internal hyperlink

change:

the pingback queue

Do self-pingbacks affect SEO?

The internal hyperlink can matter to site navigation and search-engine crawling.

The self-pingback itself is not required for that relationship.

Disabling self-pingbacks does not remove link equity

If:

<a href="https://example.com/guide/">
    related guide
</a>

remains inside the article, the internal hyperlink remains available to:

  • users;
  • search-engine crawlers;
  • site analysis tools.

The pingback record is a separate object

Preventing it does not:

  • add nofollow;
  • remove the hyperlink;
  • change the destination;
  • change the anchor text;
  • change the canonical URL.

Do not use self-pingbacks as an SEO linking strategy

Your internal-linking strategy should be based on useful contextual links.

A pingback entry in the comments system is not a substitute for good information architecture.

Do self-pingbacks affect performance?

Usually not in a way that should dominate a normal WordPress performance audit.

But self-pingbacks can trigger unnecessary work.

The processing can include

URL extraction
↓
candidate processing
↓
HTTP endpoint discovery
↓
server request
↓
XML-RPC processing
↓
source verification
↓
comment-like record creation

for a relationship that already exists entirely inside your own database and content.

Filtering the URL earlier avoids later ping processing

If an internal URL is removed at:

pre_ping

WordPress does not continue discovering and contacting the pingback endpoint for that URL.

Still, this is mainly workflow cleanup

Do not describe self-pingback removal as a major performance optimization.

The more accurate benefits are:

  • less redundant notification processing;
  • fewer unnecessary requests;
  • cleaner discussion administration;
  • clearer separation of internal links and pingbacks.

Do self-pingbacks affect security?

Stopping them removes an unnecessary same-site pingback path.

But it does not:

  • disable XML-RPC;
  • block external pingback requests;
  • prevent authentication attacks;
  • protect weak passwords;
  • patch vulnerable plugins;
  • replace rate limiting;
  • replace a WAF.

Self-pingback removal is not complete XML-RPC hardening

The security model is:

self-pingback control
→ narrow behavior

XML-RPC hardening
→ broader interface policy

authentication security
→ separate again

Incoming pingbacks deserve their own security review

If you do not want external websites to call:

pingback.ping

against your WordPress installation, review incoming pingback configuration or XML-RPC method exposure separately.

Why self-pingbacks can clutter the comments screen

Consider a documentation-heavy site with:

500 articles

and extensive contextual linking.

If many new articles reference existing articles, self-pingbacks can create a stream of records such as:

Pingback:
Guide A

Pingback:
Guide B

Pingback:
Guide C

Pingback:
Guide D

mixed with genuine:

  • reader comments;
  • reviews;
  • external pingbacks;
  • spam.

This increases moderation noise

An editor may repeatedly review notifications that contain information already visible from the posts themselves.

Self-pingbacks can be useful in some workflows

They are not universally useless.

Some publishers may appreciate seeing which newer articles link back to an older post directly from that post’s discussion area.

Conceptually:

old article
↓
pingbacks show
↓
newer internal references

This was historically more meaningful in blog-centric workflows

When content and discussion architecture were heavily centered around chronological blog posts, pingbacks could function as a visible network of references.

Modern sites often have better tools for this information

Today, internal-link analysis can come from:

  • SEO tools;
  • site crawlers;
  • editorial databases;
  • internal-link reports;
  • content-management tooling.

So the value of self-pingbacks depends on the workflow.

Should you disable WordPress self-pingbacks?

Disable them when:

  • they create administrative clutter;
  • your team does not use them;
  • the site has extensive internal linking;
  • you want external pingbacks to remain available;
  • you want internal links preserved normally.

Keep them when they are genuinely useful

For example, a small blog may intentionally use pingbacks as visible references between posts.

There is no requirement to disable them merely because a plugin offers the option.

Decision model

Do self-pingbacks provide
useful editorial information?

│
├─ Yes
│  ↓
│  Keep them
│
└─ No
   ↓
   Do you still need
   external pingbacks?

   │
   ├─ Yes
   │  ↓
   │  Filter only self-pingbacks
   │
   └─ No
      ↓
      Consider disabling
      outgoing pingbacks broadly

How to disable only self-pingbacks

Use:

pre_ping

to remove local destinations.

A minimal implementation is:

function project_disable_self_pingbacks(
    &$post_links
) {

    $home_url =
        home_url( '/' );

    foreach (
        $post_links as $key => $link
    ) {

        if (
            str_starts_with(
                $link,
                $home_url
            )
        ) {
            unset(
                $post_links[ $key ]
            );
        }
    }
}

add_action(
    'pre_ping',
    'project_disable_self_pingbacks'
);

What the code changes

Before pre_ping:

[
  https://example.com/internal-guide/,
  https://external.example/article/
]


After pre_ping:

[
  https://external.example/article/
]

What the code does not change

Inside the article:

<a href="https://example.com/internal-guide/">
    Internal Guide
</a>

remains exactly where it was.

Why use home_url()?

WordPress provides:

home_url()

to retrieve the URL where the site’s frontend is accessible.

The official home_url() documentation describes this behavior.

For a conventional site it may return:

https://example.com/

Prefix matching is simple but exact

Consider:

home_url()
https://example.com/

linked URL
https://www.example.com/post/

Those strings do not begin identically.

A simple prefix implementation can therefore miss alternate host representations.

Common URL variations include

  • HTTP vs HTTPS;
  • www vs non-www;
  • legacy domains;
  • mapped domains;
  • multilingual domains;
  • reverse-proxy hostnames;
  • subdirectory installations.

Canonical URL consistency helps

A WordPress site should ideally use one preferred URL representation consistently.

See WordPress Canonical URLs, Explained.

For domain or protocol changes, see How to Migrate WordPress URLs Safely.

Same host vs same WordPress site

A more advanced implementation might compare hostnames.

For example:

example.com/post-a/
example.com/post-b/

clearly share a host.

But consider:

https://example.com/blog/

https://example.com/shop/

They might belong to different applications under the same host.

Hostname matching can therefore be broader

You need to decide what:

self

means for your architecture.

Multisite makes the definition more complicated

Suppose a network contains:

site-a.example.com

site-b.example.com

A link between those sites may be:

internal to the network

but:

external to the individual site

There is no universal policy

You may want:

Site A
→ may ping Site B

because they operate as separate publications.

Or you may want:

all network sites
→ treated as internal

and suppress those notifications.

Test Multisite behavior deliberately.

How TheOneWP disables self-pingbacks

TheOneWP Disable Self Pingbacks uses the targeted WordPress pre_ping approach.

The verified implementation:

loads only when enabled
↓
hooks into pre_ping
↓
retrieves home_url()
↓
loops over outgoing URLs
↓
uses str_starts_with()
↓
removes matching local URLs

The module targets future outgoing self-pings

It does not:

  • edit post content;
  • remove internal links;
  • change permalinks;
  • disable XML-RPC;
  • block external pingback destinations;
  • disable trackbacks globally;
  • delete existing pingback records.

External URLs remain in the queue

If the queue contains:

https://example.com/internal/

https://wordpress.org/documentation/

the internal URL is removed while the external URL remains available for normal WordPress processing.

The module does not add frontend code

It does not require:

  • frontend JavaScript;
  • CSS;
  • REST routes;
  • extra database tables;
  • scheduled custom jobs.

It participates directly in the existing WordPress pingback pipeline.

How to test whether self-pingbacks are active

Use two controlled posts.

Step 1: create Post A

Self-Ping Test Source

Step 2: create Post B

Self-Ping Test Destination

Step 3: allow pings on Post B

This matters because a destination with pings already disabled cannot demonstrate whether outgoing self-ping filtering worked.

Step 4: add the full URL to Post A

<a href="https://example.com/self-ping-test-destination/">
    Test destination
</a>

Step 5: publish or update Post A

Allow WordPress to process its outgoing pings.

Step 6: inspect the destination

Check:

Comments
or
destination discussion records

With normal self-ping behavior

You may see:

new pingback
from Post A

With a self-pingback filter

You should see:

internal link
→ works

self-pingback
→ not created

Do not reuse a destination already pinged during the test

Because WordPress tracks previously pinged URLs, reusing the same source-destination pair can give misleading results.

Use fresh test URLs when necessary

For example:

Post A → Post B

then

Post C → Post D

for a clean second test.

Existing self-pingbacks do not prove the filter failed

Check the timestamp.

A record created:

before the filter was enabled

will remain in the database.

Disabling future self-pingbacks does not delete history

This principle is:

future behavior
≠
stored historical data

See What Happens to Old Comments When You Disable Them.

How to remove old self-pingbacks

Historical cleanup is a separate operation.

You can review pingback entries through the WordPress comments administration area and remove selected records intentionally.

For larger cleanup operations

Before bulk deletion:

  • create a database backup;
  • distinguish pingbacks from normal comments;
  • distinguish self-pingbacks from useful external pingbacks;
  • test on staging;
  • verify comment counts afterward.

Do not delete every comment-type record blindly

The comments system may also contain:

  • real visitor comments;
  • product reviews;
  • plugin-specific comment data;
  • external pingbacks;
  • trackbacks.

Self-pingbacks and complete comment disabling

If your requirement is only:

stop my own posts
pinging one another

then complete comment disabling is excessive.

A complete comments shutdown can affect much more

Depending on implementation, it can affect:

  • comment forms;
  • existing discussions;
  • product reviews;
  • comment feeds;
  • Dashboard widgets;
  • admin menus;
  • pingbacks;
  • trackbacks.

See How to Completely Disable Comments in WordPress when the site’s actual policy is to remove discussion entirely.

Common mistake: deleting internal links

The internal link is not the problem.

The automated notification is the optional layer.

Common mistake: disabling XML-RPC just to remove self-pings

This can break unrelated functionality while solving a much narrower problem.

Common mistake: using xmlrpc_enabled as a complete XML-RPC shutdown

The filter controls authenticated XML-RPC methods, not every XML-RPC capability.

Common mistake: confusing incoming and outgoing pingbacks

These are different directions:

Outgoing
→ your site sends notification

Incoming
→ your site receives notification

Common mistake: confusing pingbacks with trackbacks

Pingbacks are automated. Trackbacks are a separate legacy mechanism.

Common mistake: assuming comments and pings share one switch

WordPress stores:

comment_status

separately from:

ping_status

Common mistake: changing the site-wide Discussion setting and expecting old posts to change

Existing posts can retain their stored per-post configuration.

Common mistake: using relative URLs purely as a workaround

Relative links can affect ping detection, but a pingback-specific hook is usually a cleaner architectural solution.

Common mistake: expecting pre_ping to delete existing pingbacks

It affects future outgoing processing only.

Common mistake: treating a historical self-ping as a new one

Always check dates and run a controlled fresh test.

Common mistake: testing with the same URL repeatedly

WordPress records destinations that have already been pinged.

Common mistake: assuming no pingback means your filter worked

The destination may simply have:

  • pings disabled;
  • no pingback endpoint;
  • an XML-RPC restriction;
  • a security rule blocking the request.

Common mistake: assuming an external pingback failure is caused by self-ping filtering

A remote destination controls whether it accepts and verifies the notification.

Common mistake: forgetting protocol changes

If the site migrated from:

http://example.com

to:

https://example.com

older absolute URLs may not match a simplistic current-home prefix.

Common mistake: forgetting www variants

Likewise:

www.example.com

and:

example.com

are different strings even if they ultimately resolve to the same site.

Common mistake: forgetting domain mapping

Multilingual and Multisite systems may legitimately use several public hostnames.

Common mistake: treating self-ping removal as a complete security control

It is a publishing-workflow adjustment, not a replacement for WordPress hardening.

Common mistake: treating self-ping removal as a major speed optimization

It removes unnecessary processing, but it is not equivalent to solving a slow database, poor caching or oversized frontend assets.

Common mistake: using several overlapping controls without documentation

A site might accidentally have:

Discussion outgoing pings
→ disabled

pre_ping filter
→ active

XML-RPC pingback methods
→ removed

server XML-RPC rule
→ active

security plugin
→ blocking requests

and nobody knows which one is responsible.

Document the policy

A maintainable configuration should make clear:

Self-pingbacks
→ enabled / disabled

External outgoing pingbacks
→ enabled / disabled

Incoming pingbacks
→ enabled / disabled

Trackbacks
→ enabled / disabled

XML-RPC
→ enabled / restricted / disabled

WordPress self-pingback checklist

  • Understand that a self-pingback is not the same as an internal link.
  • Keep useful internal links intact.
  • Understand that pingbacks are automated link notifications.
  • Understand that trackbacks are a separate legacy mechanism.
  • Review Settings → Discussion.
  • Check whether outgoing pingbacks are enabled.
  • Check whether incoming pingbacks are enabled.
  • Review per-post ping status.
  • Remember that site-wide settings may not retroactively alter old posts.
  • Understand that WordPress extracts URLs from post content.
  • Understand that a post does not ping itself directly.
  • Understand that another same-site post can remain a candidate.
  • Remember that WordPress tracks previously pinged URLs.
  • Understand the role of _pingme.
  • Understand the role of do_all_pingbacks().
  • Understand the role of pingback().
  • Understand where pre_ping runs.
  • Use pre_ping for targeted outgoing self-ping filtering.
  • Modify the target list by reference.
  • Do not remove internal links merely to stop notifications.
  • Use home_url() carefully for local URL identification.
  • Consider HTTP vs HTTPS variants.
  • Consider www vs non-www variants.
  • Consider mapped domains.
  • Consider multilingual domains.
  • Consider Multisite.
  • Consider subdirectory installations.
  • Understand pingback endpoint discovery.
  • Understand the role of X-Pingback.
  • Understand the role of rel="pingback".
  • Understand that pingbacks use XML-RPC communication.
  • Do not assume xmlrpc_enabled disables pingbacks.
  • Use xmlrpc_methods only when method-level XML-RPC changes are required.
  • Keep incoming and outgoing policies separate.
  • Keep self-pingbacks and external pingbacks separate.
  • Keep comments and pingbacks separate.
  • Keep pingbacks and trackbacks separate.
  • Test with fresh source and destination posts.
  • Use an absolute internal URL during controlled testing.
  • Verify the destination accepts pings during diagnosis.
  • Check timestamps on existing pingback records.
  • Remember that disabling future self-pings does not delete historical ones.
  • Back up before bulk cleanup.
  • Do not describe self-ping filtering as complete XML-RPC hardening.
  • Do not describe it as a major SEO feature.
  • Do not describe it as a major performance optimization.
  • Document the final discussion and XML-RPC configuration.

Related guides

Final recommendation

The easiest way to understand WordPress self-pingbacks is to separate the hyperlink from the notification created around it.

The internal link is content:

Post A
→ Post B

The self-pingback is additional automated processing:

Post A
→ WordPress extracts URL
→ discovers pingback endpoint
→ sends pingback.ping
→ same site receives request
→ pingback may be stored on Post B

If that notification is useful to your editorial workflow, keep it.

If it is merely clutter, do not remove useful internal links and do not disable unrelated WordPress functionality just to stop it.

Use the narrowest appropriate control.

Need internal links
+
need external pingbacks
+
do not want self-pingbacks

→ use pre_ping

If you do not need any outgoing pingbacks:

disable outgoing ping notifications
more broadly

If you do not want incoming pingbacks:

review ping status
and XML-RPC pingback methods

If you do not need XML-RPC at all:

handle XML-RPC as
a separate compatibility
and security decision

TheOneWP Disable Self Pingbacks implements the focused approach. It hooks into WordPress’s native pre_ping stage, compares each outgoing URL with the current site home URL and removes matching same-site destinations before WordPress continues pingback processing.

The module does not edit the post, remove internal hyperlinks, disable external pingbacks, delete existing pingback records or disable XML-RPC.

The resulting model is simple:

internal linking
→ editorial decision

self-pingbacks
→ notification decision

external pingbacks
→ separate decision

XML-RPC
→ separate decision

comments
→ separate decision

Keeping those layers separate produces a WordPress configuration that is easier to understand, easier to troubleshoot and less likely to break functionality that has nothing to do with self-pingbacks.

Simplify your WordPress stack

A modular WordPress toolkit. 104 focused tools.

Ultimately, you can build cleaner workflows, maintain fewer plugins and enable only the features each website actually needs.