Hi there,
I saw this on Facebook, this without clear thoughts on how to achieve the result.
We have many Legacy Views displaying custom post types, we would like to have some way of making the 'best' stay at the top all the time...sticky.
This i saw:
"Apply an importance field to the CPT then in the view sort by importance descending then post date descending. Anything marked importance high will continue to appear first in the view"
I have tried a few ways however, do you have any advice on what I need to do ref this please?
Or any other way of doing this?
Many thanks.
Hi,
Thank you for contacting us and I'd be happy to assist.
Based on my research, WordPress only supports the sticky post feature for the native/built-in "post" type and not for the custom post types.
In my tests, I was able to achieve the required functionality using a checkbox type custom field.
1. I added a checkbox type custom field "sticky" and set it to store "1" when checked and "0" when unchecked.
( example screenshot: sticky-custom-field.png )
2. After that, in the view's ordering settings, I selected this "sticky" custom field as the primary ordering criteria and the "post date"
as the secondary ordering criteria.
( example screenshot: view-ordering-settings.png )
The "descending" order for the "sticky" custom field will ensure that all the posts where this field is checked (and have "1" as a value) are shown first and the posts where this is unchecked (and have "0" as value) are followed after.
Note: If you already have the existing posts, you'll need to update them all once, so that the correct "0" or "1" custom field values can be updated with them.
I hope this helps and please let me know if you need any further assistance around this.
regards,
Waqar
Hi there Waqar,
Thank you for your reply.
This all sounds great however the only worrying issue is:
Note: If you already have the existing posts, you'll need to update them all once, so that the correct "0" or "1" custom field values can be updated with them.
We have over 3000 custom post types, so to manually go in and update them all wouldn't be possible. Also these update regularly as they are added via a data feed. Is there no way of the 'sticky' function being not enabled to everything, only activated if we actually 'select' them?
OR -
Can we order a View based on category?
The custom posts we need are in a different taxonomy?
Thank you
Thanks for writing back.
The way custom fields query filter works in WordPress, a post that has no custom field record for the field that is being used for the filtering is ignored. This is why it is important to set '0' for the non-sticky posts, otherwise, the view will simply not show them.
There are a couple of ways you can overcome this:
1. You can make sure that when the posts are added/updated through a data feed, the '0' value is saved for that custom field for non-sticky posts and the "1" value is saved for the sticky ones.
For the posts which have already been added, you can run a custom code once, so that all of them have a "0" value to start with. You'll find an example code and steps for this, in this forum reply:
https://toolset.com/forums/topic/view-query-filter-multiple-conditions-for-the-same-field/#post-1581057
OR
2. If you don't want to maintain a "0" value for the non-sticky posts, you can update the settings of the "sticky" custom field so that it doesn't store "0" when unchecked.
Next, instead of using 1 view, you'll need to use two views on the page. The first one will be for the sticky posts and the second one will be for the non-sticky posts. The two views can be designed in the same way so that on the front-end, the results from both those views, show as one.
OR
3. If you'd prefer to achieve this using taxonomy/category, then you'll have to use the two separate views approach too, because a view's results, can't be ordered by the presence of a taxonomy/category term or not.
The first view will show all posts where the 'sticky' taxonomy term is attached and the second view below it will show all posts where it isn't attached.
HI there Waqar,
Thank you for this...appreciate your time.
So this option may be the best:
1. You can make sure that when the posts are added/updated through a data feed, the '0' value is saved for that custom field for non-sticky posts and the "1" value is saved for the sticky ones.
For the posts which have already been added, you can run a custom code once, so that all of them have a "0" value to start with. You'll find an example code and steps for this, in this forum reply:
https://toolset.com/forums/topic/view-query-filter-multiple-conditions-for-the-same-field/#post-1581057
Can I clarify.
1 - If we implement this all custom post types will default to '0'? We wont need to do this manually.
2 - We can then select which we want for 'sticky'?
3 - When the feed is updated they will always default to '0'?
The custom post types that will be 'sticky' are never touched by the feed, we manually add these...only manually added post types will ever be 'sticky'.
Finally, can you copy the exact code I would add please?
I don't know code so would use what you supply 🙂
Thank you.
To answer these specific questions, I'll need to understand the exact setup of your website, especially the post addition/update through feeds.
Can you please share temporary admin login details, along with the details of the tool that you're using for the feed import?
Note: Your next reply will be private and though no changes will be made on your website, it is recommended to make a complete backup copy, before sharing the access details.
Thank you for sharing these details.
I noticed that your website is using the "All Import" plugin for the feed import. The plugin offers a hook "after_xml_import" which can be used to execute a custom code after an import has been completed:
hidden link
You can use this hook to execute a custom function that cycles through all the published portfolio posts and sets the "sticky" custom field value to "0" if it is not already set:
function after_xml_import( $import_id, $import ) {
$target_post_type = 'portfolio';
$target_field_slug = 'sticky';
$value_to_set = 0;
$args = array(
'post_type' => $target_post_type,
'posts_per_page' => -1,
'post_status' => 'publish'
);
$posts_array = get_posts( $args );
// loop through those posts 1 by 1
foreach ($posts_array as $post) {
// get current value of the field
$current_value = get_post_meta( $post->ID, 'wpcf-'.$target_field_slug, true );
// if it is empty set the provided default value
if( empty($current_value) || !isset($current_value) ) {
update_post_meta( $post->ID, 'wpcf-'.$target_field_slug, $value_to_set );
}
}
}
add_action( 'pmxi_after_xml_import', 'after_xml_import', 10, 2 );
The above code snippet can be included through either Toolset's custom code feature ( ref: https://toolset.com/documentation/adding-custom-code/using-toolset-to-add-custom-code/ ) or through the active theme's "functions.php" file.
The rest of the steps would be the same as shared in my first reply in this thread.
( ref: https://toolset.com/forums/topic/make-custom-post-types-sticky/#post-2370513 )
As a result, all imported posts will have the 'sticky' field set to '0' and you'll have the ability to set the selective manual ones to "1".
Hey Waqar,
Wow! Thanks for that. My lack of understanding code and the fact that All Import is a new plugin meant I wouldn't know where to start ref looking for this. Thank you.
To to be clear:
I do this as you suggested earlier:
In my tests, I was able to achieve the required functionality using a checkbox type custom field.
1. I added a checkbox type custom field "sticky" and set it to store "1" when checked and "0" when unchecked.
( example screenshot: sticky-custom-field.png )
2. After that, in the view's ordering settings, I selected this "sticky" custom field as the primary ordering criteria and the "post date"
as the secondary ordering criteria.
( example screenshot: view-ordering-settings.png )
The "descending" order for the "sticky" custom field will ensure that all the posts where this field is checked (and have "1" as a value) are shown first and the posts where this is unchecked (and have "0" as value) are followed after.
Then add the exact code you supplied above to with Toolset Custom Code (which we already have used), or in the Code Snippets plugin which we already use?
So, when we run a refresh import every custom post type will have a '0' automatically added?
This important as it would need to happen on import.
Then any other custom post type we have added '1' too will remain untouched (as these do not come from the feed)
...and these will position at top of all grids?
If this is the case I'll sort this over the weekend.
Hi there Waqar,
I have followed your steps in:
The rest of the steps would be the same as shared in my first reply in this thread.
( ref: https://toolset.com/forums/topic/make-custom-post-types-sticky/#post-2370513 )
Added the the code in Toolset Custom Code.
A ran the import for all French homes.
On the France page: hidden link
I have ticked only one custom post:
hidden link
However this home is still towards the bottom of page 3....not the top of page 1.
I also noticed at the bottom of your code, ID's so I also added the import ID's...this made no difference either:
add_action( 'pmxi_after_xml_import', 'after_xml_import', 10, 2, 38, 39, 37 );
Any thoughts what I'm doing wrong?
Thank you.
Thanks for writing back.
I noticed that the '0' value was saved as expected for the portfolio post's "sticky" field, which confirms that the custom code after the import is running and performing its part, correctly.
The post order in the view was getting affected by the third-party plugin "Post Types Order". I've disabled the option "Auto Sort" from WP Admin -> Settings -> Post Types Order and the sticky post "Le Sud" is now showing as the first result.
Hi there Waqar,
Many thanks for looking into this for me.
I did see for a short while (0) beside each property title on the Toolset grids. This now gone.
The sticky works great however disabling the option "Auto Sort" now means we can't reorder Posts at all...this has no effect.
Not ideal, is this what you would expect disabling this?
The challenge is that the "Auto Sort" option from the "Post Types Order" plugin automatically changes the order by criteria for all WordPress queries (including the queries for the views) to 'menu_order'.
When this option will be checked, your order by settings from the view will be overridden too. You can get in touch with the "Post Types Order" plugin to see if they offer any hook/filter to disable this option for certain cases/queries.
I see, its not a huge issue however what you've done essentially disables all manual sorting or 'posts'.
We may as well remove the plugin altogether as now, we need to order posts by date and time....so disabling 'auto sort' renders the plugin useless.
We'll have to decide which function has the greater priority, which of course isn't your issue 🙂
Thank you for your understanding and glad I could help.
You're welcome to mark this ticket as resolved and start a new one for each new question or concern.
My issue is resolved now. Thank you!