One of the oddest remnants of the early versions of WordPress are attachment pages. I can count on one finger the number of times I’ve thought “I’d like a dedicated page for every image on my site”. Normally, unused and illogical features like this can just be ignored. However, attachment pages aren’t just a harmless remnant of a bygone era.
Attachment pages have dedicated urls, that are based on the name of the image, and overlap with the slugs you can set for posts, pages, and custom post types. Because of this, if you upload an image named faq.jpg, you may find yourself unable to add a page at the address /faq. This can negatively impact your SEO, and is an incredibly frustrating issue to try to identify and explain to clients. Beyond the URL issue, they are another template that needs to be fully themed and branded, just in case a client runs across the page by accident. As such, they need to die.
All other post types are easy to deal with, with filters and functions to control their use of URLs. Attachments stand alone with an overly-complicated and immutable permalink structure, and no simple filters attached.
There are many snippets and instructions online detailing how to remove these pages, but most (if not all) of them simply patch over the issue with a 301 redirect or a forced 404 page. Unfortunately, those authors don’t solve the root issue of reserved slugs.
So, in that light, I wrote the definitive solution to fully disable attachment pages.
Running the plugin provided below will:
- remove all rewrite rules for attachments
- prevent attachments from reserving url paths
- prefix all slugs for new attachments, in case the plugin is ever deactivated, to minimize potential name conflicts
- rewrite all references to attachment pages urls to point to the url of the file itself
- as a final fallback, in case some sort of custom code requests an attachment page via code, that page will redirect to the attachment file.
The only further change that could be made, would be to remove the references to attachment pages that appear in the media library. Unfortunately, to do so, I would have to either completely replace the backbone templates in use, as they offer no filters for this text, or I would have to blindly parse the HTML with regular expressions, which is impossible to do without introducing undocumented bugs. Neither of these solutions is particularly acceptable or future-proof. However, both places that attachment pages are referenced make reasonable sense as links to the attachment file, so the impact to the user experience is trivial. Hopefully the JavaScript over haul that is currently beginning with the Gutenberg editor will eventually lead to a more flexible media library that allows for this sort of customization.
To install the plugin, simply copy the following code to a new folder in your plugins.php directory. If there is enough interest in the comments, I will deploy the code as a plugin on the WordPress.org plugin repository, to make it simpler to install.
Matt says:
Great plugin, much appreciated. I’d suggest that you put this on github as a wordpress-plugin project with a composer.json so I can just include it in my own composer.json and reference your github link to get updates.
gschoppe says:
If I release on the WordPress plugin repository, wp-packagist will take care of that, right? If so, that seems like a more universal option for users
Leho Kraav @lkraav says:
Looks interesting. May I recommend running the code through https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards linting, the formatting as is looks super weird and hard to read.
gschoppe says:
Can you point to a specific trope or area that has you confused? My style appears to match the WordPress PHP Coding Standards.
I’ll take a look at that linter later, as it may be useful, but most of WordPress’s standards match with PSR-4 (other than tabbing), which my style is based on.
If you are having trouble with reading the
wp_unique_post_slug
function, there isn’t much I can do about that. To make it easier to patch/upgrade the plugin to match future changes to core, the logic of that function is a 1-to-1 copy of the inner portion of WordPress core’swp_unique_post_slug
function, which is unfortunately incredibly confusing to read. I could refactor, but it would make it significantly harder to patch the plugin if core changes anything in that logic, as I wouldn’t be able to generate and apply a patch file from the core code.Simmer says:
This is excellent. You might want to consider renaming it slightly, as this already has the same slug: https://wordpress.org/plugins/disable-attachment-pages/
gschoppe says:
if I release on the WordPress Repository, I’ll make sure to prefix the slug, and I definitely recommend prefixing the file name when adding to a WordPress project now (in the gist itself. the file is named gjs-disable-attachment-pages.php, to prevent conflicts), however I don’t want to stray too far from the actual task that it accomplishes, otherwise people will continue to install the version with the simpler name to google… Perhaps I’ll add in the word “Better”, or something… I’ve seen that before.
Stephen Petrey says:
Holy smokes this was helpful. Thanks greg! Handy little plugin. 🙂
Søren Friis Dam says:
Very nice plugin. I too would like to see this on the plugin repository so we can use it via wp-packagist.
Robert Caraway says:
Great plugin. Perfect solution to a very frustrating problem. A definite yes vote from me on adding to plugin repository.
Henning says:
WordPress plugin repo please!
Donna Cavalier says:
This solved a huge problem for me. Thank you!
Rochelle says:
Now if only we could change the way an image insert defaults to linking to itself! Thank you so much, could not figure out for the life of me what was creating the -2.
Greg Perham says:
Fan-flippin-tastic! Would love to see this in the plugin repository.
hexcross says:
Super awesome!!! Thanks!
One more vote for plugin repository 🙂
Dave says:
This rocks, I also vote for adding to the plugin repository!
Jeremy says:
This is great! I’d definitely vote for adding it to the Org Plugin repo.
Two questions:
1 – There’s one reference to “gjs_attachment_slug_prefix”
I’m assuming that’s a filter you have in another plugin; is it related/useful for this?
2 – The function make_attachments_private() doesn’t seem to be called; do you use this function anywhere?
Cheers!
gschoppe says:
Hi Jeremy,
The
gjs_attachment_slug_prefix
filter is provided so that users can change the default ofwp-attachment
to another value, in case they need to for some reason. This is important because the slugwp-attachment-«original-file-slug»
will still be reserved by WordPress, so it is possible that on some sites this could cause collision issues.make_attachments_private(){}
was originally hooked to theregister_post_type_args
filter, as it should cause the attachment post type to not reserve slugs. However, attachments currently ignore the standard post type arguments. I’ve re-added this hook to the to the plugin, in the hope that someday, WordPress may add support these arguments properly.Jeremy Miller says:
Makes sense on both ends! Thanks for the quick reply 🙂
Horst says:
Your plugin solves a huge problem for me. A certain service that we use bills their service by the number of pages a wordpress installation has. Unfortunately their spider counts not only the “real” pages but the attachment pages also. As we have a lot of pictures in this project we get billed higher than it has to be. So I was searching for a solution to really disable the creation of attachment pages not only to redirect them. Your plugins works fine and it is saving us money. Thank You Sir!
By the way: Don’t be too frustrated that football is not coming home in 2018! I think the english team should have won the match against croatia. Maybe in another 4 years in Catar the story will end with a happy end.
Cheers
Horst
Stephan Fischer says:
Hello, its really a great plugin, i love it!
I have some questions, for what is the flush_rewrite_rules() needed in activation and deactivation?
Thank you very much!
Best regards,
Stephan
Derek Marshall says:
Thanks for this, really appreciated. I was getting annoyed at those attachment pages.
Stephan Fischer says:
Hello,
i think the flush_rewrite_rules is not necessary in this plugin.
Best regards,
Stephan
Ce Kay says:
not even simple but also do the Job perfectly, hopefully any updates for the wordpress core system will not make bad effect !!
thanks for ur efforts and YES would like to see it as a plugin too 🙂
c.k.
Ziga says:
You are the man! Thank you for this.
Joao says:
THANK YOU. 1vote for WP official plugin, finally no more redirects and bar URLs
Jack Fogg says:
Your Plugin is Awesome!, Kindly add to WordPress Repo, so that everyone should know and use it
Andy Globe says:
i post images and link them to media file on my site
should i disable the attachment media pages?
if i do, will it affect seo?