I would like to use an ACF field to inject Schema merkup to a few specific pages on my WordPress website. Some of them are custom taxonomies or custom post types.
After a two hour research on the topic, I am still stuck.
I have created a text area field called schema_code and entered the desired Schema markup for some of my sub pages.
I currently use this code in my functions.php which does not do anything:
function acf_header_script() {
$schema = get_field('schema_code');
echo '<script type=application/ld+json>' . json_encode($schema_code) . '</script>';
}
add_action ( 'wp_head', 'acf_header_script' );
What am I missing here? Thanks a lot!
The second parameter of the ACF get_field() is required in this case, since you're not in the loop. It is either the post->ID or it's the taxonomy ID where it's {taxonomy_name}_{taxonomy_id} https://www.advancedcustomfields.com/resources/get_field/
Since you want to do this on pages and archives, etc... You need to first determine if it's a single page or an archive, etc.
function acf_header_script() {
// is it a single post?
if ( ! is_single() ) {
// no? get the queried object.
$object = get_queried_object();
if ( is_a( $object, 'WP_POST' ) ) {
$param = $object->ID;
} else {
$param = $object->taxonomy . '_' . $object->term_id;
}
} else {
// yes it's a single.
global $post;
$param = $post->ID;
}
$schema = get_field( 'schema_code', $param );
// if $schema is not empty.
if ( $schema ) {
echo '<script type=application/ld+json>' . json_encode( $schema ) . '</script>';
}
}
add_action( 'wp_head', 'acf_header_script' );
Related
I have constructed the below function to work in conjunction with a button displayed on the edit product page. It is designed to generate some description text based on the title and SKU of the product. The code works perfectly for 'simple' products, but I am struggling to get it to work for 'variable' products too.
What exactly do I need to do to get it to work correctly for both simple and variable products?
The current behaviour is:
When triggered on a simple product, it adds the new description or updates the old one to the new one.
When triggered on a variable product, it updates the main description, but deletes all variations which were previously set up on the product.
add_action('woocommerce_process_product_meta', 'update_and_save_utapd');
function update_and_save_utapd() {
if(isset($_POST['button_new_update_description'])){
$product_id = wc_get_product(get_the_ID());
$wcProduct = new WC_Product($product_id);
$get_title = $wcProduct->get_name();
$get_mpn = $wcProduct->get_meta('sp_wc_barcode_field');
$get_description = $wcProduct->get_description();
$output = '';
if(!empty($get_title)){
$output .= "<p>The " . $get_title;
}if(!empty($get_mpn)){
$output .= " (MPN: " . $get_mpn . ").";
}if(!empty($get_description)){
$wcProduct->set_description($output);
$wcProduct->save();
return "<div>SUCCESS: YOU HAVE UPDATED YOUR DESCRIPTION.</div>";
}elseif(empty($get_description)){
$wcProduct->set_description($output);
$wcProduct->save();
return "<div>SUCCESS: YOU HAVE GENERATED A NEW DESCRIPTION.</div>";
}
}
}
First when using action hooks in backend that save product data, you can't return a string (a text) as you are trying to do and anyway, it will never be displayed
Now since WooCommerce 3 you can use woocommerce_admin_process_product_object much better hook that include the WC_Product Object as function argument and there is no need to use save() method at the end of your code as once this hook is triggered the save() method is auto applied.
So we can simplify your code:
add_action('woocommerce_admin_process_product_object', 'update_and_save_utapd');
function update_and_save_utapd( $product ) {
if( isset($_POST['button_new_update_description']) ){
$name = $product->get_name();
$barcode = $product->get_meta('sp_wc_barcode_field');
$output = '';
if ( ! empty($name) ) {
$output .= "<p>The " . $name;
}
if ( ! empty($barcode) ) {
$output .= " (MPN: " . $barcode . ").";
}
$product->set_description( $output );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should better work now, without throwing errors.
With the woocommerce_process_product_meta hook you already have the product id and the product object available. Here you will find more information.
To verify that the button has been clicked you must also check its value, in addition to the isset() function.
Replace value_button with the value of the element's value
attribute
add_action('woocommerce_process_product_meta', 'update_and_save_utapd', 10, 2 );
function update_and_save_utapd( $product_id, $product ) {
// replace "value_button" with the value of the element's "value" attribute
if ( isset( $_POST['button_new_update_description'] ) && $_POST['button_new_update_description'] == 'value_button' ) {
if ( $product->is_type('simple') || $product->is_type('variable') ) {
$title = $product->get_name();
$mpn = $product->get_meta('sp_wc_barcode_field');
$description = $product->get_description();
$output = '';
if ( ! empty($title) ) {
$output .= "<p>The " . $title;
}
if ( ! empty($mpn) ) {
$output .= " (MPN: " . $mpn . ").";
}
if ( ! empty($get_description) ) {
$product->set_description($output);
$product->save();
return "<div>SUCCESS: YOU HAVE UPDATED YOUR DESCRIPTION.</div>";
} else {
$product->set_description($output);
$product->save();
return "<div>SUCCESS: YOU HAVE GENERATED A NEW DESCRIPTION.</div>";
}
}
}
}
I am currently using this code, which shows the code beginning of every post.
I want to show code in the Beginning and Ending of every post.
Can anyone help with this?
add_filter( 'the_content', 'filter_the_content_in_the_main_loop' );
function filter_the_content_in_the_main_loop( $content ) {
// Check if we're inside the main loop in a single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
return esc_html__("So Friends, How is our Article of ".get_the_title().". Do You Like it? Don't Forget to Comment below if Any Queries. For More Article regarding ".get_the_title()." Subscribe Us.").$content;
}
return $content;
}
You already know the answer. In "the_content" filter you are prepending some text to the $content variable. Now what you want to do is append. Ex:
add_filter( 'the_content', 'filter_the_content_in_the_main_loop' );
function filter_the_content_in_the_main_loop( $content ) {
// Check if we're inside the main loop in a single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
return "Beginning text" .$content . "Ending Text";
}
return $content;
}
"Beginning text" is the text that you have already added.
[2020 Jan 07]: Per OP request adding code snippet to change based on the pos category.
add_filter( 'the_content', 'filter_the_content_in_the_main_loop' );
function filter_the_content_in_the_main_loop( $content ) {
// Check if we're inside the main loop in a single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
//get categories
$categories = get_the_category();
foreach($categories as $category){
//you can check by term_id, name, slug
if($category->$term_id == $target_term_id){
return "Beginning text" .$content . "Ending Text";
}
}
}
return $content;
}
Site I’m working on is a radio show. I have a bunch of custom fields, courtesy of Advanced Custom Fields, for links to musicians’ websites, social profiles, etc.. For the last few years, we’ve used a Genesis child theme to display them, and the code I adapted worked great. The radio show’s host/producer now wants to move to a non-Genesis theme, and I’m having some trouble making it work.
Here’s an example from the site we’re migrating FROM, which includes the functioning code. (The Artist Links box, floated to the right of the main copy.)
Here’s the same post at the new site, where the code doesn’t yet display. (It will display in the same place.) FWIW, the theme is GrandBlog.
Here’s the code:
<?php
add_action ('if_artist_links');
function if_artist_links() {
// These are the custom field keys defined in the dashboard:
$metas_links = array(
'website',
'album',
'tour',
'twitter',
'facebook',
'bandcamp',
'soundcloud',
'youtube',
'instagram',
'linkedin',
'myspace',
'image',
);
// If _any_ ACF field is filled in, it's a go.
$has_meta = false; // init
foreach ($metas_links as $test ) {
if ( get_field($test) ) {
$has_meta = true;
continue; // Just need one meta field filled to create the div.
}
}
if ( $has_meta ) {
echo '<div class="custom-data artist-links">';
echo '<h2 class="artistname">' ?> <?php the_field('name') ?></h2>
<center><strong> <?php the_field('tribe') ?></strong></center> <?php
foreach ( $metas_links as $meta_links ) {
$$meta_links = get_field($meta_links);
if ( $$meta_links ) {
$f_object = get_field_object($meta_links);
$label = $f_object['label'];
echo '<div class="' . $meta_links . '">' .
'<span class="label">' . $label . '</span>' .
'</div>';
}
}
echo '</div><!-- /.custom-data -->';
}
}
?>`
Where there’s an ACF value, a link is created. Where there’s no ACF value, there’s no link. Just one link is required to make the box appear.
As far as I can tell, I’m not telling the code to run, or run in the right way. If you can help me do that, I’ll sing your praises through the weekend.
If possible, I’d really like to wrap this up in a WP plugin, for simplicity and ease of maintenance, and to put minimal code in single.php.
Thanks so much for your help!
You need to use WordPress the_content hook. Replace this in your theme's 'functions.php'.
function single_add_to_content( $content ) {
if( is_single() ) {
// These are the custom field keys defined in the dashboard:
$metas_links = array(
'website',
'album',
'tour',
'twitter',
'facebook',
'bandcamp',
'soundcloud',
'youtube',
'instagram',
'linkedin',
'myspace',
'image',
);
// If _any_ ACF field is filled in, it's a go.
$has_meta = false; // init
foreach ($metas_links as $test ) {
if ( get_field($test) ) {
$has_meta = true;
continue; // Just need one meta field filled to create the div.
}
}
if ( $has_meta ) {
$content.= '<div class="custom-data artist-links">';
$content.= '<h2 class="artistname">'.get_field('name').'</h2>
<center><strong>'.get_field('tribe').'</strong></center>';
foreach ( $metas_links as $meta_links ) {
$$meta_links = get_field($meta_links);
if ( $$meta_links ) {
$f_object = get_field_object($meta_links);
$label = $f_object['label'];
$content.= '<div class="' . $meta_links . '">' .
'<span class="label">' . $label . '</span>' .
'</div>';
}
}
$content.= '</div><!-- /.custom-data -->';
}
}
return $content;
}
add_filter( 'the_content', 'single_add_to_content' );
Or you can copy 'single.php' to your child theme and add this code directly without function.
the following code in my function.php can almost do the job nice and clean to all single pages. the problem is I want it to be filtered for a specific category ID:
function wp_add_to_content( $content ) {
if( is_single() && ! empty( $GLOBALS['post'] ) ) {
if ( $GLOBALS['post']->ID == get_the_ID() ) {
$content .= 'Your new content here';
}
}
return $content;
}
add_filter('the_content', 'wp_add_to_content');
You don't need to use get_the_category and examine the results - Wordpress already has a function to check if your post is in a category: has_category. The advantage of this over get_the_category is that
you don't need the code to loop through all results to comparing the id (this is the part that is wrong in the other answer - it will only work if your post has one single category)
You can use not just the ID, but also the slug or name
You can check for multiple categories
The code you need is very simple, you just need to change one line!
function wp_add_to_content( $content ) {
if( is_single() && ! empty( $GLOBALS['post'] ) ) {
/* pass an array with the IDs/names/slugs of the categories to check for, e.g. */
if ( has_category( array(12) ) )
$content .= 'Your new content here';
}
return $content;
}
add_filter('the_content', 'wp_add_to_content');
UPDATE:
Even though it wasn't in your question, if you actually want to include the content on all posts as well, you just need to do this:
function wp_add_to_content( $content ) {
if( is_single() && ! empty( $GLOBALS['post'] ) ) {
$content .= 'Your new content here';
if ( has_category( array(12) ) )
$content .= '<br>Your new content here';
}
return $content;
}
add_filter('the_content', 'wp_add_to_content');
Modified your code idealy this condition is never making any sense because it always getting the id. $GLOBALS['post']->ID == get_the_ID()
function wp_add_to_content( $content ) {
if( is_single() && ! empty( $GLOBALS['post'] ) ) {
if ( $GLOBALS['post']->ID == get_the_ID() ) {
$content .= 'Your new content here';
}
//getting the current post
global $post;
$category_detail=get_the_category( $post->ID );
if(!empty($category_detail))
{
$catId = $category_detail[0]->term_id;
// instead of 2 put your category id
if($catId == 2 && $catId != 0 )
{
$content .= 'Your new content here';
}
}
}
return $content;
}
add_filter('the_content', 'wp_add_to_content');
Note : above code is for only default post not for custom taxonomy for custom taxonomy
I've written two functions to show custom fields on the shop pages below each product, which can be viewed here. The ones specifically are Light Bulb Type and Coverage Area. However, these only apply to certain products. Right now, I am typing in N/A when they don't apply, but I would like to write a conditional statement to hide the entire section if the field is left empty.
Unfortunately, every time I do so, the code breaks the site because it is incorrectly written.
These are the functions I've written to show the custom fields.
add_action('woocommerce_shop_loop_item_title','show_coverage');
function show_coverage() {
echo '<span class="extra-info-head">Coverage Area:</span> ';
$coverage = get_post_meta( $post->ID );
$custom_fields = get_post_custom();
$coverage = $custom_fields['wpcf-coverage-area'];
foreach ( $coverage as $key => $value ) {
echo $value . '<br/>';
}}
add_action('woocommerce_shop_loop_item_title','show_bulbs');
function show_bulbs() {
echo '<span class="extra-info-head">Light Bulbs:</span> ';
$custom_fields = get_post_custom();
$bulbs = $custom_fields['wpcf-light-bulbs'];
foreach ( $bulbs as $key => $value ) {
echo $value;
}}
Apologies if these are poorly written and much appreciation to any suggestions and help!
*UPDATE: This was solved with a combination of the answer below and back-end options on WordPress's custom field posts.
Unfortunately, every time I do so, the code breaks the site because it is incorrectly written.
Your site is erroring out because you have an "undeclared variable."
In the callback function show_coverage(), you are using an undefined variable $post. The function doesn't know about this variable, because you haven't brought it into the function' scope.
While you could include the global $post, it's better to use the API function instead of the global variable.
$coverage = get_post_meta( get_the_ID(), 'wpcf-coverage-area' );
Let's go one step further. What if the custom metadata doesn't exist in the database? Then $coverage is not going to have anything in it. Let's protect for that by checking and then bailing out if nothing is returned.
function show_coverage() {
$coverage = get_post_meta( get_the_ID(), 'wpcf-coverage-area' );
if ( ! $coverage ) {
return;
}
echo '<span class="extra-info-head">Coverage Area:</span>';
foreach ( $coverage as $key => $value ) {
echo $value . '<br/>';
}
}
Now, let's do the same treatment to the other callback function:
function show_bulbs() {
$bulbs = get_post_meta( get_the_ID(), 'wpcf-light-bulbs' );
if ( ! $bulbs ) {
return;
}
echo '<span class="extra-info-head">Light Bulbs:</span> ';
foreach ( $bulbs as $key => $value ) {
echo $value;
}
}
Now the above functions will fetch the custom field (which is metadata). If it does not exist, you bail out. Otherwise, you start building the HTML markup and rendering it out to the browser.