#18548 closed enhancement (fixed)
Add a better option for <title> tags
Reported by: | joostdevalk | Owned by: | joostdevalk |
---|---|---|---|
Milestone: | 4.1 | Priority: | normal |
Severity: | normal | Version: | 3.3 |
Component: | Themes | Keywords: | has-patch commit |
Focuses: | template | Cc: |
Description
Right now, title tags in themes are created by using wp_title and than adding on custom code, usually bloginfo('name'), sometimes other code. Because there's basically no way for a plugin to control the entire content of a title tag, all major SEO plugins resort to output buffering.
A better way would be to output the <title> tag during the run of wp_head, based on whether the current theme has added theme_support. See attached patch for the proposed implementation. This patch also fixes the requested array filter in #17877.
Attachments (11)
Change History (124)
#2
@
13 years ago
- Cc mikeschinkel@… added
+1 to the idea and at first glance at the patch. (I would use false
instead of null
for 'pre_wp_title_tag'
hook, but otherwise looks good though I didn't look deeply at the default options after 'pre_wp_title_tag'
.) This would save me a lot of headaches related to title tags (ironically title tags came up as an issue on a conference call this very day.)
#4
@
13 years ago
@mikeschinkel i use null because than a plugin can set to false and decide to output its own title tag.
#5
follow-up:
↓ 6
@
13 years ago
I agree that something needs to be done with this. wp_title
is old, ugly, and rather inadequate (as proved by the mess of code used to generate the <title>
tag in twentyten/twentyeleven.
However, injecting the <title></title>
on wp_head
seems like the wrong solution.
I would rather see a new function altogether. Something like wp_doctitle()
. To me, wp_title()
always seemed too generic.
The new function could be available to theme developers. It could use the (vastly superior, IMO) $args
array, instead of separate parameters, set defaults, output <title></title>
tags, do the logic for outputting the title based on what is being browsed, etc. And of course, be fully filterable (early and late).
#6
in reply to:
↑ 5
@
13 years ago
Replying to nathanrice:
I'm fine with that too, it'd be a rather small fix to this patch actually, this solution was the first one Nacin and I came up with when discussing in chat.
#7
@
13 years ago
This is less crucial, but you may want to take a look at line 207 in wp-includes/default-filters.php -- looks like the whitespace/indenting is a bit mismatched to the previous/following lines.
#8
@
13 years ago
I have been working with joost on this patch and I really, really like the approach.
I think injecting <title> is the perfect solution here. The <head> is one of the messiest aspects of WordPress templating and moving toward theme support and wp_head hooks is a really elegant solution.
The null and false return values that the patch supports is really, really clever, though I'd suggest that it should be more explicit showing false !==
. That said, I'm not sure we'd even want to support a plugin from bypassing a <title> tag removal with false. Just my take.
#9
follow-up:
↓ 14
@
13 years ago
As a not-theme designer, I think removing the <title> entirely from hardcoded structure is a bit too extreme. Clueless people forking twentyeleven or using it as an example are bound to forget it.
I don't see how having <title><?php one_simple_filtered_function(); ?></title> is less performant.
#11
@
13 years ago
- Cc marko@… added
The thing what I miss is backward compatibility. Since all the themes still will use wp_title() it now will send twice the <title></title> tag.
#12
follow-up:
↓ 13
@
13 years ago
Personally I wish the user could set the format of the title tag in Settings, just like permalinks. Maybe that's just me; I dislike that it is controlled by the theme since it seems like more of a global/browser thing than a design thing.
#13
in reply to:
↑ 12
;
follow-up:
↓ 15
@
13 years ago
Replying to markoheijnen:
The thing what I miss is backward compatibility. Since all the themes still will use wp_title() it now will send twice the <title></title> tag.
Not true, you have to declare theme support for this in your theme for it to work first. 100% backwards compatible, that's the main reason for choosing this solution.
Replying to jane:
Personally I wish the user could set the format of the title tag in Settings, just like permalinks. Maybe that's just me; I dislike that it is controlled by the theme since it seems like more of a global/browser thing than a design thing.
I agree Jane, this is perfect groundwork for that next step though.
#14
in reply to:
↑ 9
@
13 years ago
Replying to ozh:
As a not-theme designer, I think removing the <title> entirely from hardcoded structure is a bit too extreme. Clueless people forking twentyeleven or using it as an example are bound to forget it.
I don't see how having <title><?php one_simple_filtered_function(); ?></title> is less performant.
The issue I have with that is not about performance, it's the fact that theme designers think they have something to do with the page title when they don't: it's content.
#15
in reply to:
↑ 13
@
13 years ago
Replying to joostdevalk:
Replying to jane:
Personally I wish the user could set the format of the title tag in Settings, just like permalinks. Maybe that's just me; I dislike that it is controlled by the theme since it seems like more of a global/browser thing than a design thing.
I agree Jane, this is perfect groundwork for that next step though.
+1 to this!
#16
@
13 years ago
I agree with Joost. <title><?php one_simple_filtered_function(); ?></title>
wouldn't solve anything.
People would just start adding stuff before/after it again, since it's the most obvious way to do it.
#17
@
13 years ago
Ah you are right about that.
Would love to see how Jane proposed it. That it gives you some default way to create the title or you can create custom way of creating the title.
#18
@
13 years ago
Let me make it clear why the add_theme_support is there in the first place: that's backwards compatibility only. If we didn't do it that way loads of sites using old themes would end up with two titles.
#20
follow-up:
↓ 21
@
13 years ago
Maybe you should add an option $echo to the function _wp_render_title_tag() that defaults to true. Setting it to false would allow devs to call the function and to let it return the value without the title tags. Obviously the filter 'wp_title_tag_array' allows for further manipulation of the title but maybe some devs would like to be able to use the page title elsewhere on the page as well ( without having to mimic the base functionality ).
I know that maybe the function name doesn't make too much sense anymore in that case but if we were to seperate the actual 'rendering' from the 'wrapping' in title tags that issue would be solved as well.
#21
in reply to:
↑ 20
;
follow-up:
↓ 22
@
13 years ago
Replying to ldebrouwer:
No. One of the reasons wp_title can't be patched now is because it's used in plugins for other (wrong) uses. If we prevent that from happening stuff can't break because people use things wrong. That's why, in fact, I tend to agree with nacin that we probably shouldn't even allow the removal of the title altogether...
#22
in reply to:
↑ 21
@
13 years ago
Replying to joostdevalk:
Ah, right. Good and very valid point.
#23
@
13 years ago
The idea is that _wp_render_title_tag() is an internal function to WP only. If anything, I'd be willing to include a doing_action() call in there just so it needs to be called on wp_head and can't be abused. So -1 to an echo parameter.
We should also force the add_theme_support to be done befoe or on init, to prevent it from being added in header.php or template_redirect to ensure it is accessible from the backend for future compatibility.
#25
@
13 years ago
+1 to this idea.
I tend to lean toward using a function within the theme between <title>
tags. Using add_theme_support()
and having WP automatically put the title in there is great for backwards compatibility until you look at child themes.
If a user overwrote header.php
within their child theme but their parent theme updated to use the new functionality, the user would have two <title>
tags. If we just create a replacement function for wp_title()
, this won't be a problem. The user will still use old functionality if they overwrote header.php
in their child theme, but at least they'd only have a single <title>
tag.
#26
follow-up:
↓ 27
@
13 years ago
So what? The second title tag, from the parent theme, will simply be ignored by the browser.
#27
in reply to:
↑ 26
@
13 years ago
Replying to scribu:
So what? The second title tag, from the parent theme, will simply be ignored by the browser.
So, some of us care about these type of things and don't want a bazillion questions from theme users. That's what.
#28
follow-up:
↓ 31
@
13 years ago
Again, if there's no perceivable change (besides not passing the W3C validator), what's the problem, exactly?
#29
@
13 years ago
Also, we could do a check to handle the edge case you mentioned. Nevermind, that wouldn't work.
#31
in reply to:
↑ 28
;
follow-up:
↓ 32
@
13 years ago
Replying to scribu:
Again, if there's no perceivable change (besides not passing the W3C validator), what's the problem, exactly?
The problem has already been described. You already understand what the problem is and don't need further explanation. Either you accept it as a legitimate issue or you don't.
I've merely provided this as constructive feedback on this ticket. Feel free to ignore it or use it.
#32
in reply to:
↑ 31
@
13 years ago
Replying to greenshady:
Either you accept it as a legitimate issue or you don't.
I agree that it is a legitimate issue; generating two <title>
tags is not a good practice.
#33
follow-up:
↓ 34
@
13 years ago
Replying to joostdevalk:
That's why, in fact, I tend to agree with nacin that we probably shouldn't even allow the removal of the title altogether...
There's a lot of code in your patch, and while I agree with the need to at least call 'wp_title'
I'd like to see a bypass of the rest of the code for those pages that don't need all of your new code to run.
Maybe pass the results returned by the 'pre_wp_title_tag'
hook through the 'wp_title_tag'
hook instead of just echoing the results and instead of not having a 'pre_wp_title_tag'
hook.
#34
in reply to:
↑ 33
@
13 years ago
Replying to mikeschinkel:
Replying to joostdevalk:
That's why, in fact, I tend to agree with nacin that we probably shouldn't even allow the removal of the title altogether...
There's a lot of code in your patch, and while I agree with the need to at least call
'wp_title'
.
We're not going to use wp_title or any of its filters. The reason for that is there have been several attempts at doing that and they all break because of how wp_title is used in plugins. A patch to do that by Nacin a while back actually had to be reverted because of it. So you can rule that one out.
I do understand what greenshady is saying, we'll have to give that another thought. If we opt for a template tag I would opt for one that outputs the <title> tag, so the only way of changing the title is still by applying filters to the content and giving plugins access to the entirety of the title tag content as well as allowing us to change title structures from the backend as Jane suggested.
#35
@
13 years ago
As you can see I've also coded out an alternate version, which creates a new template tag and indeed uses the standard $args way of adding options. This might be easier to handle... I'm fine with both versions myself.
#36
@
13 years ago
wp_title_tag() looks like the best approach.
Easier to switch to and avoids the inherent problems with wp_title().
The only drawback is that you can't automatically detect wether a theme is using wp_title() or wp_title_tag(). We could add a theme support flag for that later, though.
#37
@
13 years ago
wp_title_tag() does indeed solve one problem by including <title> tags in its output.
Unfortunately, it's inherently less flexible, so it's not really going to convince anyone to use it. It also requires a function call, so it's not backwards compatible out of the box. And, since it doesn't require support registrations, it's not forwards compatible either, with stuff we may (and want to) do in the admin.
When talking with Joost I proposed a way to handle the issues raised here very elegantly. Essentially, we could prevent our new title tag from being rendered if wp_title() has already been called. At the time, we dismissed it as silly for anyone to do this, as they'd instantly see the mistake. However, greenshady brings up an excellent point about child themes. So let's move forward with the idea.
The attached patch:
- Requires that add_theme_support('title-tag') is fired on the after_setup_theme or init hooks, or in the body of functions.php. By doing this, it requires that support can be discerned in the admin for a possible future feature. This is enforced using doing_action(), which was proposed in #14994. (This patch is designed to work without applying that patch, however.) I really like this, and I think that add_theme_support() should have this kind of enforcement for all kinds of theme support.
- Prevents a title tag from being rendered if wp_title() has already been called, by checking to see if the wp_title hook has already been fired.
- Requires that _wp_render_title_tag() is only called internally on the wp_head hook. This enforces it as an internal hook callback rather than the potential it gets used as a title tag.
- Adds a new return value for add_theme_support() of WP_Error.
- Removes the
false
return from the pre_wp_title_tag hook. The only way to bail is to provide a title to be printed. Continues to treat pre_wp_title_tag as a short-circuit filter that bails immediately, in line with many other pre hooks in WordPress.
Remember, requires #14994 for most of this.
#38
@
13 years ago
I like that last approach, just updated the patch a bit to handle titles for date archives better as the original code for that in wp_title was goofy.
#42
follow-up:
↓ 43
@
13 years ago
- Cc 24-7@… added
I really don't understand why this "patch" is needed. I can't imagine a real reason for not using the filter that already comes with wp_title();
. Pushing stuff like this into core is like gasoline for the discussions about "WordPress is bloat ware". Imho the structure inside the function is good, but general-template.php
is the wrong place. This should be part of Twenty Eleven to teach people how to do it right. I think this will bring up much more confusion than help.
Anyway, if this really makes it's way into core, here are the things I want to mention to improve the internal structure of _wp_render_title_tag();
:
- Use an associative array for
$title
as it's easier to understand how to overwrite parts for non-tech savy users (a.k.a. the majority). - Using the wrong hooks is imo not a real Error. Switch to
_doing_it_wrong();
. Using the wrong hook happens to the best devs all the time and using that function is much more polite (From the doc block of_doing_it_wrong();
: Marks something as beeing incorrectly called). - I'm not a big fan of different coding styles - if you want to call it like this - inside a single function. From
title-tag-3.diff
:$title = implode( " $sep ", $title );
vs.echo '<title>' . $pre . "<title>\n";
doesn't help much to make core more readable and easier to understand. - The same goes for
if ( null !== $pre = apply_filters( 'pre_wp_title_tag', null ) ) {
. Having the filter attached to$pre
one line earlier makes it much easier to read. - I'd rename the
pre_wp_title_tag
filter towp_title_tag_walker
. Imo it's nothing else. - About input
$args
and$defaults
: We got the wonderful function namedwp_parse_args();
in core - which is imo used not often enough. Why not use this and make an easy to read/understand array of default values at the beginning and then parse it with the data received viaadd_theme_support();
?
Just my 2 cents (I still think this function shouldn't be added just because plugins/themes are missusing the wp_title();
filter.
#43
in reply to:
↑ 42
;
follow-up:
↓ 44
@
13 years ago
Replying to F J Kaiser:
Just my 2 cents (I still think this function shouldn't be added just because plugins/themes are missusing the
wp_title();
filter.
if people mis-use it .. they have a reason to do so
#44
in reply to:
↑ 43
;
follow-up:
↓ 45
@
13 years ago
Replying to ramoonus:
if people mis-use it .. they have a reason to do so
The most wide spread reason to do so is "not knowing it better".
#45
in reply to:
↑ 44
;
follow-up:
↓ 47
@
13 years ago
Replying to F J Kaiser:
Replying to ramoonus:
if people mis-use it .. they have a reason to do so
The most wide spread reason to do so is "not knowing it better".
The issue is, we can't from one release to another suddenly change the way we do things. Twenty Eleven is at is right now, we'll change that if this patch goes in, but hundreds of people will have copied it and we'll need to make sure it stays working without ANY work on their side. We do however also want to make it better for people who have a need for that, hence, this patch.
#47
in reply to:
↑ 45
@
13 years ago
Replying to joostdevalk:
The issue is, we can't from one release to another suddenly change the way we do things.
Haven't we already had twentyten_filter_wp_title();
? Correct me if I'm wrong.
Leaving this aside: What will then happen when we got Twenty Twelve? Will we then remove this "feature" from core again?
As you're already brought add_theme_support();
in your patch, why not add wp_render_title_tag();
into the functions.php file of Twenty Eleven encapsuled into something like if ( current_theme_supports( 'title_tag', array( $args ) ) ) { add_filter( ...etc... );
} so child themes could use it adding a single call to theme support to gain the advantage. This wouldn't break anything, leaves core unbloated & we could finally move a better title tag into Twenty Tweleve that is activated by default.
#51
@
13 years ago
I think that title-tag-3.diff is missing the default-filters.php changes. I think you still need to attach _wp_render_title_tag()
to wp_head so it's called somehow:
add_action( 'wp_head', '_wp_render_title_tag', 1 );
#54
follow-up:
↓ 55
@
13 years ago
- Cc jmlworld@… added
I'm not sure why we'd add another function into the already bloated core when wp_title()
can exactly do what we need if we use it the correct way. I see the whole purpose of introducing this new function is to hard-code <title></title>
tag into the WordPress core, which defeats the "separation of design & content" rule.
Jane's suggestion of introducing an option to set the format of the <title>
tag in Settings would stop people abusing the wp_title()
tag. The lack of standard option to modify the structure of the title tag was the first motive of developers abusing the tag.
Teaching people how to add template tags the correct way would be a better idea. Updating the codex and removing themes and plugins abusing the system would also encourage theme/plugin developers to correct their mistakes.
<title>
tag is not content, it's design. The content inside it is the content and adding <title><?php title_tag_function(); ?></title>
in the theme's header.php
is the correct practice, in my opinion.
WordPress was intended to be simple and flexible, and hardcoding things in the wp_head()
will result developers creating their own correct_wp_head()
because they have an excuse.
#55
in reply to:
↑ 54
;
follow-up:
↓ 56
@
13 years ago
Replying to jamalorg:
The short answer is: backwards compatibility.
Basically if we change wp_title to do the things that themes are already doing OUTSIDE wp_title, then we'll break all those themes. Adding this new functionality will allow us to encourage themes to switch to this and eventually deprecate wp_title.
#56
in reply to:
↑ 55
;
follow-up:
↓ 57
@
13 years ago
Replying to aaroncampbell:
Basically if we change wp_title to do the things that themes are already doing OUTSIDE wp_title, then we'll break all those themes. Adding this new functionality will allow us to encourage themes to switch to this and eventually deprecate wp_title.
Well. Introducing a new filterable template tag, probably without args, would do no harm. I didn't get the idea of hard-coding <title></title>
tags inside the function. This is annoying approach.
#57
in reply to:
↑ 56
@
13 years ago
Replying to jamalorg:
Well. Introducing a new filterable template tag, probably without args, would do no harm. I didn't get the idea of hard-coding
<title></title>
tags inside the function. This is annoying approach.
The reason for doing that is that otherwise the simplest thing to do for theme coders would be to add something within the <title></title>
and not using the filters, the way they do now. To prevent that, we output the <title>
completely outside of the theme and force everyone to use the filters, thus making sure each and every plugin has access to it.
#58
follow-up:
↓ 59
@
13 years ago
I still don't get why this is really needed. Teaching devs is what codex is for and not the core itself. And if you really want to teach people directly through template tags, use _doing_it_wrong();
and extend the wp_title();
function.
This is the first function I see in core that is a "parallel" function. Normally core has wrapper functions for such stuff. Example: function wp_title_tag() { echo '<title>'.wp_title( null, false ).'</title>';
}. If you want to add fancy stuff in there: fine. But actually doubling most part of the original function makes imo no sense.
@joostdevalk: You still didn't answer any of my above concerns or discuss any of the suggestions I made or alternatives I offered. This gives me the feeling that it's just about "boxing" this through.
#59
in reply to:
↑ 58
@
13 years ago
Replying to F J Kaiser:
I still don't get why this is really needed. Teaching devs is what codex is for and not the core itself. And if you really want to teach people directly through template tags, use
_doing_it_wrong();
and extend thewp_title();
function.
This is the first function I see in core that is a "parallel" function. Normally core has wrapper functions for such stuff. Example:
function wp_title_tag() { echo '<title>'.wp_title( null, false ).'</title>';
}. If you want to add fancy stuff in there: fine. But actually doubling most part of the original function makes imo no sense.
@joostdevalk: You still didn't answer any of my above concerns or discuss any of the suggestions I made or alternatives I offered. This gives me the feeling that it's just about "boxing" this through.
Sorry you feel that way but I think you're not getting our points. The goal is to:
- have a new, better way of doing titles, without messing without causing issues with all themes that are currently out there. This absolutely, 100%, rules out changing the way
wp_title()
works. You might think that we should train devs better, but our real concern are users, not devs, who end up with wonky titles on their blogs because their theme is old and they don't know how to change it. So backwards compatibility is paramount. - second, learning from our earlier mistakes, we do not want themes to be able to change what's in the title in any other way than plugins can, so we need to make the entire contents of the title tag filterable through 1 filter. The only way of making 100% sure of that is outputting the
<title>
tags through the code. We can't do that withinwp_title
, you'll understand why because of the point above. - finally, we will probably, if this fix goes in, end up deprecating
wp_title
.
Make sense now? Any concerns I left unanswered?
#60
follow-up:
↓ 61
@
13 years ago
- Cc chip@… added
I'm clearly missing something. I don't see any need for a new function at all. The wp_title()
function and wp_title
filter are fully functional. If the problem is developer education, then the solution is not to introduce new code into core, but rather to educate developers.
If there is to be a best-practice implementation of wp_title()
/wp_title
, then let's revise the Theme Review Guidelines, and enforce that implementation for repository-hosted Themes. It would be a simple matter to require that Themes not modify wp_title()
directly in the template, but only through the wp_title
filter.
But what is currently proposed appears to me to be nothing more than 200 lines of code to accomplish something that can be done without adding a single line of code.
As for the assertion that the doctitle content is content rather than presentation: I say that it's just the opposite. The doctitle is presentation, rather than generation, of content. Thus, it logically may be controlled by the Theme - even if that control needs to be standardized, such that the Theme plays nicely with Plugins.
#61
in reply to:
↑ 60
@
13 years ago
Replying to chipbennett:
But what is currently proposed appears to me to be nothing more than 200 lines of code to accomplish something that can be done without adding a single line of code.
+1. IMHO this is addressing a problem that doesn't really exist (namely that themes have more control over the <title> than plugins do). If a theme contains nothing more than wp_title('')
in the <title> tag then plugins have complete control over the title. Most 'SEO' plugins ask users to ensure this is the case, and so be it.
All this change will accomplish is that SEO plugins will need to ask users to ensure their theme doesn't contain a <title> tag at all, rather than asking them to ensure it only contains wp_title('')
. I don't believe that achieves anything.
#62
follow-ups:
↓ 63
↓ 66
@
13 years ago
The big issue with just keeping wp_title()
is how to handle is_front_page()
. Currently, wp_title()
does not output anything for the front page. This has left it up to theme devs to add in something to display on the front page, which makes it tough for plugins to filter since there's no hook.
Changing the function to output something for the front page would obviously introduce backwards-compatibility issues.
#63
in reply to:
↑ 62
@
13 years ago
Replying to greenshady:
The big issue with just keeping
wp_title()
is how to handleis_front_page()
. Currently,wp_title()
does not output anything for the front page. This has left it up to theme devs to add in something to display on the front page, which makes it tough for plugins to filter since there's no hook.
Changing the function to output something for the front page would obviously introduce backwards-compatibility issues.
What's wrong with Themes using the wp_title
filter to add content when is_front_page()
?
But, regardless: either Themes/Plugins can filter wp_title
to add is_front_page()
content, or the wp_title()
function can be modified to accommodate is_front_page()
- neither of which requires this patch.
#64
@
13 years ago
Themes/Plugins can filter wp_title to add is_front_page() content
Yes, themes could do that all along, except they don't.
or wp_title() function can be modified to accommodate is_front_page()
Just going to paste what greenshady said right before your comment:
Changing the function to output something for the front page would obviously introduce backwards-compatibility issues.
#66
in reply to:
↑ 62
@
13 years ago
Replying to greenshady:
The big issue with just keeping
wp_title()
is how to handleis_front_page()
. Currently,wp_title()
does not output anything for the front page. This has left it up to theme devs to add in something to display on the front page, which makes it tough for plugins to filter since there's no hook.
Changing the function to output something for the front page would obviously introduce backwards-compatibility issues.
Please explain this for me if you could. Never mind here.
Thanks!
#67
@
13 years ago
Replying to johnbillion:
All this change will accomplish is that SEO plugins will need to ask users to ensure their theme doesn't contain a <title> tag at all, rather than asking them to ensure it only contains
wp_title('')
. I don't believe that achieves anything.
Actually, you're right; a theme could signal that it uses wp_title() correctly with add_theme_supports( 'enhanced_wp_title' )
, which could then be leveraged by SEO plugins and by Core to add some output for is_front_page() etc.
#68
@
13 years ago
Actually, you're right; a theme could signal that it uses wp_title() correctly with add_theme_supports()
And at that point, it'd be easier to remove all markup from their purview. Then they need to do things in one location, rather than two. Simplifies everything and makes it difficult to screw up.
#70
@
13 years ago
Replying to scribu:
Themes/Plugins can filter wp_title to add is_front_page() content
Yes, themes could do that all along, except they don't.
So, is it really preferable to introduce 200 lines of code, a new template tag, and a new add_theme_support()
call, instead of simply educating Theme developers on the best practice for modifying doctitle content?
How is it going to be any easier to educate Theme developers to use a new template tag (plus add a new add_theme_support()
call), instead of just educating Theme developers to filter wp_title
instead of passing a string directly to wp_title()
?
Personally, as a member of the team that will largely be tasked with the education/enforcement of whatever implementation method is ultimately chosen, I think getting Theme developers to use existing code is going to be much easier than trying to get them to use a new template tag.
The past of least resistance (and fastest adoption) is going to be to say, "move your wp_title()
-filtering code out of header.php
, wrap it in a function in functions.php
, and hook it into add_filter( 'wp_title', 'themename_filter_wp_title' )
".
#71
@
13 years ago
There won't be any new template tag. There will just be an add_theme_supports() call.
See nacin's comment: http://core.trac.wordpress.org/ticket/18548#comment:68
#72
follow-up:
↓ 83
@
13 years ago
Replying to scribu:
Actually, you're right; a theme could signal that it uses wp_title() correctly with
add_theme_supports( 'enhanced_wp_title' )
, which could then be leveraged by SEO plugins and by Core to add some output for is_front_page() etc.
I like this idea. A lot.
It greatly simplifies everything and keeps us from having extra code added.
#73
follow-up:
↓ 80
@
13 years ago
So, is it really preferable to introduce 200 lines of code, a new template tag, and a new add_theme_support() call, instead of simply educating Theme developers on the best practice for modifying doctitle content?
Yes. This isn't a new template tag.
The 200 lines of code are copy-pasted from the current wp_title(), and improved for context and performance. In many cases these are backwards incompatible changes, mostly outlined in previous comments.
wp_title() will be deprecated in a future release, probably when core supports a UI for title tag manipulation. (See comments from jane above.)
The past of least resistance (and fastest adoption) is going to be to say, "move your wp_title()-filtering code out of header.php, wrap it in a function in functions.php, and hook it into add_filter( 'wp_title', 'themename_filter_wp_title' )".
I disagree on both counts. This path is more work, without a doubt. Some of them might not even know what a filter is or how it works.
The new instructions would be: No more template tag, no more wp_title(), no more messy code in between your <title> tags. Just use add_theme_support('title-tag');
and you're done. It's pretty much idiot proof, and that's the idea.
#74
follow-up:
↓ 77
@
13 years ago
I would be willing to punt this to 3.4 and spearhead a UI for title tag manipulation. Then the user benefits will be obvious for developers.
#75
follow-up:
↓ 76
@
13 years ago
Past freeze. Punt implies it was in 3.3, though, but it's still in awaiting review. Agree to 3.4 target.
#76
in reply to:
↑ 75
@
13 years ago
Replying to jane:
Past freeze. Punt implies it was in 3.3, though, but it's still in awaiting review. Agree to 3.4 target.
Indeed. By punt I meant mark.
I still want to continue the discussion here uninterrupted on the cost-benefit analysis.
#77
in reply to:
↑ 74
@
13 years ago
Replying to nacin:
I would be willing to punt this to 3.4 and spearhead a UI for title tag manipulation. Then the user benefits will be obvious for developers.
Add UI for meta description as well and we can wrap this up once and for all. If someone wants to use plugin they're more than welcome :)
#78
follow-up:
↓ 79
@
13 years ago
Replying to nacin:
The past of least resistance (and fastest adoption) is going to be to say, "move your wp_title()-filtering code out of header.php, wrap it in a function in functions.php, and hook it into add_filter( 'wp_title', 'themename_filter_wp_title' )".
I disagree on both counts. This path is more work, without a doubt. Some of them might not even know what a filter is or how it works.
Most are already aware of filters at this point. The rest would benefit greatly from learning what a filter is and how to use it. All are capable of learning.
The new instructions would be: No more template tag, no more wp_title(), no more messy code in between your <title> tags. Just use
add_theme_support('title-tag');
and you're done. It's pretty much idiot proof, and that's the idea.
By all means, correct me if my inference here is incorrect, but IMHO this sounds like an effort to discourage - if not prevent (as I suspect Plugin developers would prefer) - Theme developers from modifying the doctitle content.
For Theme developers that currently modify the output of wp_title()
, I think I can safely assume that many would still want to modify the doctitle content, even using this new method. So, to say, "No more template tag, no more wp_title(), no more messy code in between your <title> tags. Just use add_theme_support('title-tag');
and you're done" won't be sufficient, because they're left without instructions for modifying the doctitle content.
And even when wp_title()
is deprecated, I still don't see the benefit of introducing a separate
filter to use. If Theme developers are using the wp_title
filter properly by the time wp_title()
is deprecated, then that filter would (should) remain sufficient for whatever the new implementation is.
#79
in reply to:
↑ 78
;
follow-up:
↓ 82
@
13 years ago
Replying to chipbennett:
By all means, correct me if my inference here is incorrect, but IMHO this sounds like an effort to discourage - if not prevent (as I suspect Plugin developers would prefer) - Theme developers from modifying the doctitle content.
Correct.
They would be able to pass defaults through the add_theme_support() call, and I imagine these default settings would be akin to what power they're normally given in wp_title(). Additionally, there would be filters in this new callback, though I'd hesitate to suggest a theme should use it.
Point is, themes shouldn't be dealing with the content of a title tag. It's exactly that: content. Not presentation.
The biggest problem right now is a theme can optionally take absolute control over what appears in the title by avoiding wp_title() all together. We'd rather force our own <title> tag to ensure that a user or plugin can equally make modifications. It's not that a theme would lose all power, it's that they would be on equal footing. It's the same idea as wp_title('')
but wp_title() is crap, our own default themes even want something better, we can't change it without breaking old themes, and we will need the add_theme_support() registration in order to show a user interface in the admin.
#80
in reply to:
↑ 73
@
13 years ago
Replying to nacin:
The new instructions would be: No more template tag, no more wp_title(), no more messy code in between your <title> tags. Just use
add_theme_support('title-tag');
and you're done. It's pretty much idiot proof, and that's the idea.
If the intent is to really make it that simple then I am all for it ... making things easier for the end-user, AFAIK, has always been the ultimate goal.
Although this may not directly affect the end-user at this time, or maybe even for a few versions, the end result will be easier modification of the output by plugins and themes which would serve at a minimum as an indirect benefit by default.
#82
in reply to:
↑ 79
@
13 years ago
Replying to nacin:
Replying to chipbennett:
By all means, correct me if my inference here is incorrect, but IMHO this sounds like an effort to discourage - if not prevent (as I suspect Plugin developers would prefer) - Theme developers from modifying the doctitle content.
Correct.
They would be able to pass defaults through the add_theme_support() call, and I imagine these default settings would be akin to what power they're normally given in wp_title().
It would be instructive to see an example of this written up in code-form; I ran through the ticket, patches, and comments so quickly that I'm not exactly sure what the current state of everything is.
Additionally, there would be filters in this new callback, though I'd hesitate to suggest a theme should use it.
Point is, themes shouldn't be dealing with the content of a title tag. It's exactly that: content. Not presentation.
I disagree; an argument could easily be made that the doctitle content is simply presentation. It is not new/unique content; rather, it's simply presentation of already generated/defined content.
I think the best solution is for this presentation to be defined in core, both through more robust doctitle markup in core, and through a UX for user configuration. That way, neither Theme nor Plugin needs to modify the doctitle content.
So, I understand where you're going with the add_theme_support()
. Though, why not just make it assumed? There was certainly no add_theme_support()
added for the Admin Bar, which required wp_footer()
to be present.
(I guess what I'm saying is that I'd like to see better-defined, more-consistently defined "WordPress standard" practices, implemented more consistently. Too many such features are handled differently from each other.)
The biggest problem right now is a theme can optionally take absolute control over what appears in the title by avoiding wp_title() all together. We'd rather force our own <title> tag to ensure that a user or plugin can equally make modifications.
In the short-term, that is equally (and more easily) achievable by changing the Theme Review Guidelines with respect to wp_title()
, to require that if modified, it must be modified via filter.
It's not that a theme would lose all power, it's that they would be on equal footing.
I'm with you 100% on this.
It's the same idea as
wp_title('')
but wp_title() is crap, our own default themes even want something better, we can't change it without breaking old themes, and we will need the add_theme_support() registration in order to show a user interface in the admin.
I think you could convince me, if the UX and more-robust core doctitle markup were implemented simultaneously (along with wp_title()
deprecation), so that Theme developers both only needed to make one change to Theme code, and would benefit from a significantly reduced need to filter the doctitle content in the first place.
#83
in reply to:
↑ 72
@
13 years ago
Replying to greenshady:
Replying to scribu:
Actually, you're right; a theme could signal that it uses wp_title() correctly with
add_theme_supports( 'enhanced_wp_title' )
, which could then be leveraged by SEO plugins and by Core to add some output for is_front_page() etc.
I like this idea. A lot.
It greatly simplifies everything and keeps us from having extra code added.
Looks like the easiest and most elegant approach to me. No extra tags or complications, just introducing another hookable theme support.
#84
@
13 years ago
That's not quite true. Keeping wp_title() around will result in some gnarly code, both in Core and in plugins, due to the fact that wp_title() itself sucks and is hard to extend.
#87
@
13 years ago
- Cc gaarai@… added
First, let me say that I do like to talk a lot. I apologize for that. I always want to put reason behind code. If you don't care to understand my approach to how I created my patch, just try out the patch and go from there.
I decided to create a new patch that is current with trunk while also implementing a new approach that I think solves some problems. The patch is merely a suggestion. I think the names and some of the methodology definitely needs some tweaking.
After thinking about the problem of titles for a while, I've come to the conclusion that there are four interested parties when it comes to title modification:
- Title Setters - This is code that needs to set the original title of the content. Good examples are BuddyPress, Pods, and WP e-Commerce. These are plugins that create new content types and need to filter the title in order to set the actual title of the content.
- Title Modifiers - This is code that needs to augment or change the title. I only know of a couple examples off the top of my head, but I'm sure there would be more if I dug around. The first example is NextGEN Gallery which adds new title sections such as Gallery, Slideshow, etc as appropriate. The next one is Anonymizer which uses the wp_title filter to remove author's names.
- SEO Plugins - These plugins set the final title that is displayed. Sometimes the title needs to be completely replaced and sometimes it needs to modify the existing title in order to set up the final title format.
- Themes - Themes are stuck in an odd spot. If they simply call wp_title, the titles look ugly. If they then use the wp_title filter, plugin authors quickly get frustrated that themers are making their job hard. It's a no-win situation.
After looking through the ways different parties are using the current wp_title
filter, I see some key problems with the current system:
- Relying on a single filter for all needs is far too simple and leads to issues. This can be seen by the fact that most every
wp_title
filter that I've seen uses a priority a 10. The ones that don't use the default priority seem to have no pattern to their choices. I've seen 0, 1, 9, 11, 90, 99, and 100 used. It is clear that some want to be early and some want to be late with only a few realizing that they are not the only filter in town. - Many developers completely ignore the
sep
orseplocation
variables. Some seem to do this because they feel them to be unnecessary or unwanted. This makes for quite a mess when more than one filter is involved. - There is no way to know when the title is "done". If a filter already finished the title by adding the site name or some other modification, a later filter has no way of knowing this. A number of plugin authors have suggested writing compatibility checks that look for their plugin in order to take a back seat when the plugin is present. This sounds good, but a quick search on the plugin repo shows 972 "seo" plugins. Of course, only some of these are in the
wp_title
filter game, but I'd rather not have to go through the latest version of every one of those plugins on any schedule in order to ensure proper compatibility. This clearly is not the solution. - Since the title generated by the
wp_title
function isn't exactly the same as just the content title (as it may or may not have a separator on it), it cannot be reliably used for title modification when more complex changes need to be made. This results in a large amount of duplication as plugins reimplement the entire stack of if statements to determine the title of the specific page being viewed.
From all of this, I decided that the new title system needed to have some specific approaches:
- A theme should be able to simple add theme support for a title-specific feature and let WordPress take it from there. However, arguments can be passed to the
add_theme_support
function call in order to modify the default values that WordPress uses. This is already covered in the patch supplied by Joost and will be the same approach I take in my patch. - WordPress is fully responsible for assembling the final title. This will prevent issues with titles being a hodgepodge of multiple attempts to assemble a full title. It will also remove any need for most people working with titles to care anything about the separator or the directionality of the title.
- Since the parties above can be divided into those that want to set the content title and those that want to set the final title, there should be two processes/steps for generating the title: one for the content title and one for the final title.
- The title should stay as an array until it is ready to be assembled.
- A sort of templating system should be used to ensure maximum flexibility while still allowing WordPress to reliably assemble the final title.
The power of my approach comes from the format of the arguments added by the theme support system. The defaults as found in my patch should give an idea.
$defaults = array( 'sep' => ' - ', 'direction' => 'auto', // auto, rtl, ltr // %%TITLE%% is a special variable but can still be overridden if desired. 'title_format' => array( '%%TITLE%%', '%%PAGING%%', '%%BLOGNAME%%' ), 'title_format-home' => array( '%%BLOGNAME%%', '%%PAGING%%', '%%DESCRIPTION%%' ), 'title' => '', 'title-archive' => __( 'Archive' ), /* translators: 1: author name */ 'title-author-archive' => __( 'Author Archive for %1$s' ), /* translators: 1: date description */ 'title-date-archive' => __( 'Archive for %1$s' ), /* translators: 1: post type archive title */ 'title-post-type-archive' => __( 'Archive for %1$s' ), /* translators: 1: search phrase */ 'title-search' => __( 'Search Results for "%1$s"' ), /* translators: 1: taxonomy name */ 'title-taxonomy-archive' => __( 'Archive for %1$s' ), 'title-404' => __( 'Page not found' ), 'variables' => array( /* translators: 1: page number */ 'PAGING' => __( 'Page %1$d' ), 'BLOGNAME' => get_bloginfo( 'name' ), 'DESCRIPTION' => get_bloginfo( 'description' ), ), );
The sep
and direction
(new name for seplocation
) are a bit different from before.
The sep
now has optional spaces. The spaces are only present if you actually supply spaces around the separator. This is because not all languages use spaces. Specifically, the Chinese, Japanese, and Thai written languages and the original Korean written language don't have any spaces. If you do some searches on a search engine using one of these languages (Chinese, Japanese, Thai), you will see plenty of titles that have separators but don't have any spaces. Thus, it makes not sense to force spaces. Titles have spaces around the separator if they are desired.
It seems that many people thought that seplocation
is unnecessary. I assume that they base this off of the SEO principal that if you add the site's title to the title tag, it needs to go at the right. However, this is true just because English is a left-to-right language. There are a number of languages that are right-to-left: Arabic, Hebrew, N'Ko, Syriac, Thaana, and other less well-known languages. If you search on a search engine using one of these languages (Arabic, Arabic, Hebrew), you will notice that the directionality of many of the titles are flipped. I have to imagine that the SEO principal of title directionality should flip for the right-to-left languages. Even if this isn't the case, given that it makes sense for people searching to see the content title first, it should definitely be an option that doesn't require significant effort (such as implementing a custom title solution) to change.
The direction
entry defaults to 'auto'
. When this is set to auto, the code uses is_rtl
to determine the language directionality and sets direction
of the title accordingly. The direction
can also be manually set by using 'ltr'
or 'rtl'
.
The title_format
entries are used to supply the format used by the final title (the use of the underscore helps to prevent name collisions with the title}} entries). The {{{title
entries are for the content title (this could be changed to content_title
, but I left it as title
for simplicity). The variables
entries are used to provide drop in replacements in any of the template_format
entries. This allows someone to modify a template without having to recreate additional code, such as the paging code.
Notice the title_format-home
entry. This sets a format to be used for just the home view. The same system can be used for the title
entries as the title-post-type-archive
entry shows. The code generates a string or array of "views" that the current patch represents. This basically creates a template hierarchy system that allows for great specificity with title
and title_format
entries.
title_format
entries can make use of the variables
entries while the title
entries can optionally use a sprintf
variable which represents the generated content title (if the active title
entry for a page doesn't have this variable and the generated content title isn't empty, the generated content title is used as-is and the title
entry is ignored).
The process flow works like this:
- The theme calls
add_theme_support('title-tag')
and optionally passes in an argument array. - The
add_theme_support
function merges in the passed in arguments if thetitle-tag
support is added more than once. - The
_custom_theme_features_just_in_time
function runs. If the theme hastitle-tag
support, it runs the jitadd_theme_support
call and adds awp_head
action (priority of 0 in order to add the title early in the action stack) to call the title rendering function. - The
_wp_render_title_tag
function runs on thewp_head
action. - Run the
pre_wp_title_tag
filter. If a title is returned, print it in title tags and exit the function. This allows SEO plugins and other similar code to sidestep the entire title generating process and supply their own title. - Pull in the arugments from the theme supports system and filter them with the
title_tag_options_filter
filter. Yes, code can useadd_theme_support
calls to modify the arguments, but this has a number of problems. The primary issue is that only a theme should call this as other code should be checking first to see if thetitle-tag
is supported by the theme, and since there aren't any standards on whenadd_theme_support
should be called by a theme, it would quickly present problems of some plugins running the check before the theme has a chance to run the function. So, a filter is the logical choice that allows maximum flexibility without introducing implementation complexity. - Run the
title_tag_filter
filter. This allows code to supply the content title and would be used by plugins such as BuddyPress, Pods, and WP e-Commerce. - All outside interaction is done at this point. WordPress takes care of everything else.
- The typical stack of ifs is run in order to decide what page is being looked at. As before, a relevant content title is generated (some date archives, time archives, the 404 page, and other page possibilities that aren't covered don't receive a content title). However, my patch also creates a
$view
variable that stores a string or array that represents the view of the current page. For instance, a non-static page home view is'home'
and a category archive isarray('category-taxonomy-archive', 'taxonomy-archive', 'archive')
. The view is important as it is used to find the appropriatetitle}} and {{{title_format
to use to generate the final title. - Locate the appropriate
title
andtitle_format
. - If the
title
from the arguments containssprintf
variable, replace it with the content title, and use this as the new content title. - If the
direction
is'rtl'
, thetitle
andtitle_format
arrays are reversed. Yes, both of them can be arrays. Making thetitle
support an array structure allows for plugins such as NextGEN Gallery to easily augment the title with the addition of a "Gallery" title section. It also allows for building the classic multi-part date archive titles. - Loop through the
title_format
array and replace any foundvariables
from the arguments. While doing this, remove any now-empty array entries. This prevents from having duplicated separators. - Turn the
title_format
andtitle
arrays into strings by imploding them using thesep
argument. - Replace instances of the
%%TITLE%%
special variable found in thetitle_format
with thetitle
variable. - Print the title tag and contents.
There is definitely room for improvement. I need to implement some more robust date archive titles as well as creating a time archive section. Some efficiency and naming improvements should also be made.
This patch is primarily to help push the conversation forward in the hopes of having a final solution soon.
For themes to implement the solution from the patch, simply remove the wp_title
function call and title tag from the theme and add code such as the following to the functions.php
file:
add_theme_support( 'title-tag', array( 'sep' => ' → ' ) );
For code that supplies new content titles:
function example_supply_title( $title ) { // Run conditional to determin if a new title needs to be supplied return 'New title'; } add_action( 'title_tag_filter', 'example_supply_title' );
Notice how the format of the title remains. Only the content title is replaced.
For code that wants to replace all the titles:
function example_replace_all_titles( $title ) { // Code to load desired new title return 'New title'; } add_action( 'pre_wp_title_tag', 'example_replace_all_titles' );
For code that wants to filter the arguments:
function example_modify_title_arguments( $arguments ) { // Any necessary conditional code in case the modifications aren't static $arguments['sep'] = ' | '; $arguments['variables']['EX_CUSTOM'] = 'Custom'; $arguments['title_format-singular'] = array( '%%TITLE%%', '%%PAGING%%', '%%EX_CUSTOM%%' ); return $arguments; } add_filter( 'title_tag_options_filter', 'example_modify_title_arguments' );
</longpost>
#88
@
13 years ago
Thanks for the thorough explanation of your patch Chris. I really like this approach. The original patch by Yoast didn't make it a lot easier for plugins to avoid stepping on each other's toes. Using an associative array solves this (I use a similar system for breadcrumb components in my theme framework).
The only major problem I can see with the patch is that the pre_wp_title_tag
filter is ripe for abuse. By allowing plugins to hook into this filter we actually undo all the other hard work that allows the separate title components to be filtered.
If one single plugin on your site decides to use the pre_wp_title_tag
filter then we're back at square one and all our hard work is for nothing. The main title_tag_filter
filter hasn't run at this point, so changes to the content title made by another plugin is not going to be taken into account. I'd like to recommend removing the pre_wp_title_tag
filter.
#94
@
11 years ago
- Component changed from Template to Themes
- Focuses template added
- Keywords needs-codex removed
I feel like rather than this being something the theme declares, there should be an intuitive (and simplistic) title tag builder in General Settings. Why should the theme be specifying separators and such? That's more content than anything.
#95
@
11 years ago
Related: #17877 introduced a new filter which will need to be considered for back-compat purposes.
#96
@
10 years ago
- Keywords twenty-fifteen added
Submitted a simplified patch that could serve as a v1 in lieu of a title tag builder in the admin.
I agree with nacin that it shouldn't be for themes to decide what kind of separator to use or in what order to display the title bits, so in 18548.2.diff it doesn't accept an args array anymore.
I'm hesitant to move in 4.1 without a mature patch, but it would be great if we could agree on a v1, get it in with 4.1, and promote its usage with Twenty Fifteen. Heck, it could even be as rudimentary as 18548.3.diff, it would still give us the freedom to do what ever we want with the output at a later point in time.
This ticket was mentioned in IRC in #wordpress-dev by obenland. View the logs.
10 years ago
#99
@
10 years ago
- Keywords needs-docs added
- Milestone changed from Awaiting Review to 4.1
It would be preferable to add some information to the DocBlock for wp_title()
describing the new 'title-tag' theme support and expected output.
#100
follow-up:
↓ 101
@
10 years ago
[30074] broke a unit test on this line: https://core.trac.wordpress.org/browser/trunk/tests/phpunit/tests/theme/support.php#L60. It's not clear at a glance why this is happening, but git bisect
tells no lies.
#101
in reply to:
↑ 100
;
follow-up:
↓ 102
@
10 years ago
Replying to boonebgorges:
[30074] broke a unit test on this line: https://core.trac.wordpress.org/browser/trunk/tests/phpunit/tests/theme/support.php#L60. It's not clear at a glance why this is happening, but
git bisect
tells no lies.
Interesting. r30074 introduced _wp_render_title_tag()
, which the test checks for in line 54. The tests were introduced here, adding tests for a patch on this ticket. I'm pretty sure they can all be removed.
#102
in reply to:
↑ 101
@
10 years ago
Replying to obenland:
Interesting. r30074 introduced
_wp_render_title_tag()
, which the test checks for in line 54. The tests were introduced here, adding tests for a patch on this ticket. I'm pretty sure they can all be removed.
Thanks for the link. You're right that the reason these tests just started failing now is because the function_exists()
check finally started running.
I looked back through the history of current_theme_supports()
, and it looks to me like the types
array and the rand_str() => rand_str()
array would never have worked. current_theme_supports( 'post-thumbnails' )
checks (and has always checked) for post support on specific post types with in_array( $content_type, $_wp_theme_features['post-thumbnails'][0] )
. A string $content_type will only ever pass this test if the array is flat; array( 'types' => array( 'post', 'page' ) )
is not. And a specific content_type string will only pass the check if it actually matches an item in the array; when you register with rand_str()
and check again with another rand_str()
, it'll fail. No one ever noticed that these tests incorrectly described current_theme_supports()
because they never got that far :)
#104
@
10 years ago
- Keywords has-patch dev-feedback twenty-fifteen needs-docs removed
- Milestone changed from 4.1 to Future Release
We've done what we're going to do for 4.1. Moving to future release.
#105
@
10 years ago
- Keywords has-patch 2nd-opinion added
- Milestone changed from Future Release to 4.1
The message for the _doing_it_wrong()
added in [30074] feels wrong. The context is misused, should be a translators comment. Also the message is to general IMO. 18548-_doing_it_wrong.patch is based on the message we have for scripts and styles: "Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks."
This ticket was mentioned in Slack in #core by ocean90. View the logs.
10 years ago
#109
@
10 years ago
- Keywords commit added; 2nd-opinion removed
The new version of the string makes much more sense.
Patch to add title tag functionality