I just launched my new website. Everything is working ok, HOWEVER, I just noticed the HTML docs (source code of the page) has 15 blank lines before "<!doctype html>". This is causing some issues for SEO and to generate automatic sitemaps.
I searched all over the web, and finally find the issue: the functions.php in my child theme (storefront). When I delete or rename the functions.php in the child theme, the HTML doc is shown normally without blank spaces. I tried deleting one by one the functions coded in the file, but the issue persists until I delete all functions together. Also, I disabled all plugins and nothing solves, only deleting the mentioned file. Any ideas? Thank you very much!
below is the current content of functions.php
add_filter( 'woocommerce_product_tabs', 'my_remove_all_product_tabs', 98 );
function my_remove_all_product_tabs( $tabs ) {
unset( $tabs['description'] ); // Remove the description tab
unset( $tabs['reviews'] ); // Remove the reviews tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
return $tabs;
}
?>
<?php // Este snippet regula el tiempo que se muestra el cart widget del WCPT
function wcpt_cart_js() {
?>
<script type="text/javascript">
// your javscript code goes here
jQuery(function($){
$('body').on('wcpt_cart', function(){
setTimeout(function(){
$('.wcpt-cart-widget ').fadeOut();
}, 2000); // delay
})
})
</script>
<?php
}
add_action('wp_head', 'wcpt_cart_js');
?>
<?php
/* quitar "Menu" del hamburger en moviles */
add_filter( 'storefront_menu_toggle_text', 'storefront_menu_toggle_text' );
function storefront_menu_toggle_text( $text ) {
$text = __( '' );
return $text;
}
?>
<?php
/* quitar la barra menu inferior nativa storefront en moviles
add_action( 'init', 'jk_remove_storefront_handheld_footer_bar' );
function jk_remove_storefront_handheld_footer_bar() {
remove_action( 'storefront_footer', 'storefront_handheld_footer_bar', 999 );
}*/
?>
<?php
/**
* Custom Filter for Gallery Image Captions
*
* Note: Avoid altering captioning, selector, and item tag.
*/
function mlc_gallery_image_caption($attachment_id, $captiontag, $selector, $itemtag) {
$id = $attachment_id;
// Grab the meta from the GIC plugin.
$my_image_meta = galimgcaps_get_image_meta($id);
/**
* Here's where to customize the caption content.
*
* This example uses the meta title, caption, and description.
*
* You can display any value from the $my_image_meta array.
* You can add your HTML too.
*/
/*
return "<{$captiontag} class='wp-caption-text gallery-caption' id='{$selector}-{$id}'>" .
"Title: " . $my_image_meta['title'] . "<br>" .
"Caption: " . $my_image_meta['caption'] . "<br>".
"Description: ". $my_image_meta['description'] .
"</{$captiontag}></{$itemtag}>";
*/
return "<{$captiontag} class='wp-caption-text gallery-caption' id='{$selector}-{$id}'>" .
$my_image_meta['caption'] . "<br>".
"</{$captiontag}></{$itemtag}>";
}
add_filter('galimgcaps_gallery_image_caption', 'mlc_gallery_image_caption', 10, 4);
?>
<?php
/**
* Cambia el texto del boton "anadir al carrito"
*/
add_filter('woocommerce_product_single_add_to_cart_text','QL_customize_add_to_cart_button_woocommerce');
function QL_customize_add_to_cart_button_woocommerce(){
return __('Comprar', 'woocommerce');
}
?>
<?php
/**
* Override theme default specification for product # per row
*/
function loop_columns() {
return 4; // n products per row
}
add_filter('loop_shop_columns', 'loop_columns', 999);
?>
<?php
add_filter('woocommerce_product_add_to_cart_text', 'archive_custom_cart_button_text');
function archive_custom_cart_button_text()
{
return __('Comprar', 'woocommerce');
}
?>
<?php
add_filter( 'woocommerce_get_price_html', 'add_price_prefix', 99, 2 );
function add_price_prefix( $price, $product ){
$price = '' . $price;
return $price;
}
?>
<?php
if (wp_is_mobile()){
add_filter( 'the_title', 'shorten_woo_product_title_mobile', 10 , 2 );
/*mobile_storefront_page_header();*/
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 );
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 6 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_show_product_images', 7 );
}
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );
?>
<?php
function shorten_woo_product_title_mobile( $title, $id ) {
if ( ! is_singular( array( 'product' ) ) && get_post_type( $id ) === 'product' && strlen( $title ) > 20 ) {
return substr( $title, 0, 42) . '..'; // change last number to the number of characters you want
} else {
return $title;
}
}
?>
<?php
function mobile_storefront_page_header() {
if ( is_single() ) {
return;
}
?>
<header class="entry-header">
<?php
the_title( '<h1 class="entry-title">', '</h1>' );
storefront_post_thumbnail( 'full' );
?>
</header><!-- .entry-header -->
<?php
}
?>
<?php
/**
* Redirecciona el productos de los resultados en tabla a la pagina seo optimizada del producto agrupado
*/
add_action('template_redirect','custom_shop_page_redirect');
function custom_shop_page_redirect(){
global $post;
if (class_exists('WooCommerce')){
if(is_product()){
$product = get_product( $post->ID );
if( $product->is_type( 'grouped' ) ){
$slug = get_queried_object()->post_name;
$nslug = str_replace("tienda/","",$slug);
for ($x = 0; $x <= 20; $x++) {
$nslug = rtrim($nslug,$x);}
$nslug = rtrim($nslug,"-");
wp_safe_redirect(home_url($nslug));
exit();
}
}
}
return;
}
?>
<?php
/**
* cambia el formato del precio de agrupados
*/
add_filter( 'woocommerce_grouped_price_html', 'grouped_price_range_delete', 'grouped_price_prefix', 10, 3, 2 );
function grouped_price_range_delete( $price, $product, $child_prices) {
$price = '';
return $price;
}
?>
<?php
/**
* actualiza automaticamente el carrito al cambiar la cantidad
*/
add_action( 'wp_footer', 'cart_update_qty_script' );
function cart_update_qty_script() {
if (is_cart()) :
?>
<script>
jQuery('div.woocommerce').on('change', '.qty', function(){
jQuery("[name='update_cart']").trigger("click");
});
</script>
<?php
endif;
}```
I'm very sorry. Is now solved, i found the problem was the blank lines between each php open/close. Sorry for the useless post.
Regards!
Related
I wrote this code for display description tab on the left and upsell product on the right in the layout of woocommerce single product. But how avoid this html code if a product have no upsell products at all, and return to the original layout?
This is my custom code:
/*** Display description tab and upsell products side by side */
add_action( 'woocommerce_after_single_product_summary', 'ckde_open_container_desc_upsells', 0 );
function ckde_open_container_desc_upsells() {
echo '<div class=" grid kc-desc-upsells-content"><div class="col-60 kc-desc-container">';
}
add_action( 'woocommerce_after_single_product_summary', 'ckde_close_open_col_desc_upsells', 15 );
function ckde_close_open_col_desc_upsells(){
echo '</div><div class="col-40 kc-upsells-container">';
}
add_action( 'woocommerce_after_single_product_summary', 'ckde_close_col_upsells', 20 );
function ckde_close_col_upsells(){
echo '</div></div>';
}
/*** Change number of upsells output */
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15);
add_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_upsells', 15);
if (!function_exists('woocommerce_output_upsells')) {
function woocommerce_output_upsells() {
woocommerce_upsell_display(6,3); // Display max 6 products, 3 per row
}
}
For sure there is a hook or a conditional tag to do that, but I can't figure out what it can be.
I don't want to override woocommerce template file but do this in my custom functions file
I hope it is clear enough.
Thanks a lot for the help.
I solved in this way finally!
/*** Display description tab and up-sell products side by side when up-sell products are defined */
add_action( 'woocommerce_after_single_product_summary', 'ckde_open_container_desc_upsells', 0 );
function ckde_open_container_desc_upsells() {
global $product;
if ( isset( $product ) && is_product() ) {
$upsells = $product->get_upsell_ids();
if ( count( $upsells ) > 0 ) {
echo '<div class=" grid kc-desc-upsells-content"><div class="col-60 kc-desc-container">';
}
}
}
add_action( 'woocommerce_after_single_product_summary', 'ckde_close_open_col_desc_upsells', 15 );
function ckde_close_open_col_desc_upsells() {
global $product;
if ( isset( $product ) && is_product() ) {
$upsells = $product->get_upsell_ids();
if ( count( $upsells ) > 0 ) {
echo '</div><div class="col-40 kc-upsells-container">';
}
}
}
add_action( 'woocommerce_after_single_product_summary', 'ckde_close_col_upsells', 20 );
function ckde_close_col_upsells() {
global $product;
if ( isset( $product ) && is_product() ) {
$upsells = $product->get_upsell_ids();
if ( count( $upsells ) > 0 ) {
echo '</div></div>';
}
}
}
I customise my woocommerce account pages by adding new endpoints successfully.
The title oh this new endpoints is "My account" default title. I would like to customize the title as well.
I tried with the hook "woocommerce_endpoint_{endpoints}_title", which works perfectly on defaults endpoints, but it doesn't seem to work on custom endpoint :
My custom endpoint (not working):
add_filter( 'woocommerce_endpoint_favoris_title', 'change_my_account_favoris_title', 10, 2 );
function change_my_account_favoris_title( $title, $endpoint ) {
$title = __( "Tests", "woocommerce" );
return $title;
}
Custom endpoint
Default endpooint example working:
add_filter( 'woocommerce_endpoint_edit-account_title', 'change_my_account_edit_title', 10, 2 );
function change_my_account_edit_title( $title, $endpoint ) {
$title = __( "Tests", "woocommerce" );
return $title;
}
Default endpoint
Can't find anything on this for now,
Thanks for your time
EDIT:
My complete hooks of my woocommerce account section:
1/ Creation of endpoints :
add_filter ('woocommerce_account_menu_items', 'custom_log_history_link', 40);
function custom_log_history_link($menu_links){
$menu_links = array_slice( $menu_links, 0, 5, true )
+ array( 'favoris' => 'Mes favoris' )
+ array_slice( $menu_links, 5, NULL, true )
+ array( 'delete-account' => 'Supprimer mon compte' )
+ array_slice( $menu_links, 5, NULL, true );
return $menu_links;
}
add_action( 'init', 'custom_add_endpoint' );
function custom_add_endpoint() {
add_rewrite_endpoint( 'favoris', EP_PAGES );
add_rewrite_endpoint( 'delete-account', EP_PAGES);
}
2/ Content of new endpoints:
add_action( 'woocommerce_account_favoris_endpoint', 'custom_my_account_endpoint_content_favoris' );
function custom_my_account_endpoint_content_favoris() {
$user = wp_get_current_user();
$user_id=$user->ID;
$favoris=get_field('liste_des_favoris','user_'.$user_id);
$favoris_id=array();
echo "<h3>Vos produits favoris :</h3>";
if ($favoris!=''){
foreach ($favoris as $favori) {
$favoris_id[] = $favori['produit_favori'];
}
echo '<ul class="list-produits">';
foreach($favoris as $favori){
$product=wc_get_product($favori['produit_favori']);
$product = $product->get_data();
$sidebar = true;
ItemProduit($product,$sidebar,$favoris_id,$user_id);
}
echo '</ul>';
} else {
echo "<p>Vous n'avez pas de favoris pour le moment1.</p>";
}
}
add_action( 'woocommerce_account_delete-account_endpoint', 'custom_my_account_endpoint_content' );
function custom_my_account_endpoint_content() {
echo "<p>Etes-vous sûr de vouloir supprimer défintivement votre compte ?<br/>Attention ! Toute suppression de compte est définitive, vous perdrez tout l'historique de vos achats.<br/>En supprimant votre compte, toutes vos données personnelles seront définitivement effacées de notre base de données.</p>";
echo '<p class="status"></p>';
wp_nonce_field( 'ajax-delete-nonce', 'delete-security' );
echo '<div class="btns-delete">';
echo '<div class="btn btn-red" id="submit-delete">Supprimer</div>';
echo '</div>';
}
3/ Custom menu order :
add_filter ( 'woocommerce_account_menu_items', 'custom_sort_menu' );
function custom_sort_menu( $menu_links ){
$menu_links = array(
'dashboard' => 'Tableau de bord',
'orders' => 'Mes commandes',
'favoris' => 'Mes favoris',
'edit-address' => 'Mes adresses',
'edit-account' => 'Détails du compte',
'customer-logout' => 'Déconnexion',
'delete-account' => 'Supprimer mon compte',
);
return $menu_links;
}
To allow the composite filter hook woocommerce_endpoint_{$endpoint}_title to work with custom My Account endpoints, there is something missing from your code. You need to declare those endpoints as query vars in woocommerce_get_query_vars filter hook as follows:
add_filter( 'woocommerce_get_query_vars', 'myaccount_custom_endpoints_query_vars' );
function myaccount_custom_endpoints_query_vars( $query_vars ) {
$query_vars['favoris'] = 'favoris';
$query_vars['delete-account'] = 'delete-account';
return $query_vars;
}
Then to change that custom endpoints titles you can use effectively:
add_filter( 'woocommerce_endpoint_favoris_title', 'change_my_account_favoris_title' );
function change_my_account_favoris_title( $title ) {
return __( "Favoris", "woocommerce" );
}
add_filter( 'woocommerce_endpoint_delete-account_title', 'change_my_account_delete_account_title' );
function change_my_account_delete_account_title( $title ) {
return __( "Supprimer mon compte", "woocommerce" );
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Remember to refresh rewrite rules by saving changes on Wordpress settings "Permalinks" section.
Other notes:
In your actual code, you are using 2 times the hook woocommerce_account_menu_items in 2 functions… You need just one of them
One way of changing the title of the custom WooCommerce endpoints is to use the_title filter with the in_the_loop conditional
Here is an example that you'll need to modify per your own requirements.
function wpb_woo_endpoint_title( $title, $id ) {
if ( is_wc_endpoint_url( 'downloads' ) && in_the_loop() ) { // add your endpoint urls
$title = "Download MP3s"; // change your entry-title
}
elseif ( is_wc_endpoint_url( 'orders' ) && in_the_loop() ) {
$title = "My Orders";
}
elseif ( is_wc_endpoint_url( 'edit-account' ) && in_the_loop() ) {
$title = "Change My Details";
}
return $title;
}
add_filter( 'the_title', 'wpb_woo_endpoint_title', 10, 2 );
I would like to ask additional info about this topic:
How can I merge the Description and Additional Information tabs in WooCommerce?
My only problem is I want the additional info displayed first. This is a screenshot:
https://i.stack.imgur.com/UTIbf.png
Here is the link to the site: https://adisport.hu/termek/adidas-xz-torsion/
This is the code I used in function.php:
// Remove Additional Info tab
add_filter('woocommerce_product_tabs', 'remove_tab_additional_info', 30);
function remove_tab_additional_info($tabs){
unset( $tabs['additional_information'] );
return $tabs;
}
// Add original Additional Info tab info to the end of the_content
add_filter('the_content','add_details_to_content', 10, 1);
function add_details_to_content($content){
if ( is_product() ){
global $product;
$content = '<div class="product-description">'.$content.'</div>';
ob_start();
?><div class="product-additional-info"><?php
$heading = apply_filters( 'woocommerce_product_additional_information_heading', __( 'Additional information', 'woocommerce' ) );
if ( !empty($heading) ) {
?>
<h3><?php echo esc_html( $heading ); ?></h3>
<?php }
do_action( 'woocommerce_product_additional_information', $product );
?></div><?php
$content .= ob_get_clean();
}
return $content;
}
Try the following:
// Remove Additional Info tab
add_filter( 'woocommerce_product_tabs', 'remove_tab_additional_info', 30 );
function remove_tab_additional_info( $tabs ){
unset( $tabs['additional_information'] );
return $tabs;
}
add_filter( 'the_content', 'add_additional_info_before_content' );
function add_additional_info_before_content( $content ){
if ( is_product() ){
global $product;
ob_start();
echo '<div class="product-additional-info">';
$hook = 'woocommerce_product_additional_information_heading';
$heading = apply_filters( $hook, __( 'Additional information', 'woocommerce' ) );
if ( !empty($heading) ) {
echo '<h3>' . esc_html( $heading ) . '</h3>';
}
do_action( 'woocommerce_product_additional_information', $product );
echo '</div>';
$content = ob_get_clean() . '<div class="product-description">' . $content . '</div>';
}
return $content;
}
Tested and works.
Related: Add custom content to WooCommerce product description
I am using WooCommerce Version 2.6.13 because the latest version of WooCommerce is not supporting my theme. I need to rename the product tab and tried to use the following snippet to rename tabs. But it does not work.
add_filter( 'woocommerce_product_tabs', 'woo_rename_tabs', 98 );
function woo_rename_tabs( $tabs ) {
$tabs['description']['title'] = __( 'تفاصيل' ); // Rename the description tab
return $tabs;
}
tabs.php
<?php
/**
* Single Product tabs
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Filter tabs and allow third parties to add their own
*
* Each tab is an array containing title, callback and priority.
* #see woocommerce_default_product_tabs()
*/
$tabs = apply_filters( 'woocommerce_product_tabs', array() );
if ( empty($tabs) ) {
return;
}
$tab_keys = array_keys( $tabs );
$active_tab_key = array_shift( $tab_keys );
?>
<div id="shopreviews" class="tours-tabs">
<ul class="nav nav-tabs">
<?php foreach ( $tabs as $key => $tab ) {
printf( '<li%s>%s</li>',
$key == $active_tab_key ? ' class="active"' : '',
$key,
apply_filters( 'woocommerce_product_' . $key . '_tab_title', $tab['title'], $key )
);
}; ?>
</ul>
<div class="tab-content">
<?php foreach ( $tabs as $key => $tab ) {
if ( empty( $tab['content'] ) && ! empty( $tab['callback'] ) ) {
ob_start();
call_user_func( $tab['callback'], $key, $tab );
$tab['content'] = ob_get_clean();
}
printf(
'<div class="tab-pane %s" id="tab%s">' .
'<div class="tours-tabs__content padding-all">%s</div>' .
'</div>',
$key == $active_tab_key ? 'in active' : 'fade',
$key,
$tab['content']
);
} ?>
</div>
</div>
This is my page http://royalfalconholidays.com/arabic/tours/exotic/ and I have to rename the the title 'Details' to arabic.
Any suggestions? Perhaps there is a different/better method ?
I'm not sure why this snippet doesn't work for you:
add_filter( 'woocommerce_product_tabs', 'woo_rename_tabs', 98 );
function woo_rename_tabs( $tabs ) {
$tabs['description']['title'] = __( 'تفاصيل' ); // Rename the description tab
return $tabs;
}
But there's another filter you can use (which you've already tried..): woocommerce_product_description_tab_title:
add_filter( 'woocommerce_product_description_tab_title', function(){
return 'تفاصيل';
} );
And if you want to change the title of the other tabs:
add_filter( 'woocommerce_product_photos_tab_title', function(){
return 'Title for the "photos" tab';
} );
So just substitute description with the tab's key — e.g. photos for the "Photos" tab.
I have a question about a WooCommerce shop I am currently working on. The shop only contains only two languages, Dutch and English.
Is it possible when somebody from Poland visits the English version of the webshop and then navigates to the WooCommerce Products page it does not show the "Add to Cart" option but displays a different button with another link based on IP-adres (Geo-Location)?
EDIT
Ok, I managed to get it to work but not with your example:
// Wijzigingen Links en teksten knoppen toevoegen
function custom_product_button(){
// GEOLocatie aanroepen en verschillende distrubiteurs toevoegen
$geoip = geoip_detect2_get_info_from_current_ip();
$country = $geoip->raw[ 'country' ][ 'iso_code' ];
$button_text = __( "To distributor's website", "woocommerce" );
$button_usa = 'https://google.com';
$button_singapore = 'https://www.google.com.sg';
// Tonen van buttons met verschillende linkjes
?>
<form class="cart">
<input type="submit" value="<?php echo $button_text; ?>" onClick="window.open('<?php if ( 'US' === $country ) {echo $button_usa;}if ( 'SG' === $country ) {echo $button_singapore;}?>');"class="single_add_to_cart_button button alt">
</form>
<?php
}
// Vervangen van de button op single product pagina
add_action( 'woocommerce_single_product_summary', 'replace_single_add_to_cart_button', 1 );
function replace_single_add_to_cart_button() {
global $product;
$geoip = geoip_detect2_get_info_from_current_ip();
$country = $geoip->raw[ 'country' ][ 'iso_code' ];
if ( 'US' === $country || 'SG' === $country)
{
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary', 'custom_product_button', 30 );
}
}
// Vervangen van de button op loop pagina en categorie / archief pagina
add_filter( 'woocommerce_loop_add_to_cart_link', 'replace_loop_add_to_cart_button', 10, 2 );
function replace_loop_add_to_cart_button( $button, $product ) {
$geoip = geoip_detect2_get_info_from_current_ip();
$country = $geoip->raw[ 'country' ][ 'iso_code' ];
if ( 'US' === $country || 'SG' === $country) {
$button_text = __( "View product", "woocommerce" );
$button = '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
}
return $button;
}
Maybe not the best coded piece but it is working in combination with the Plug-in GeoIP Detection.
Your coding looks much better but doen't seem te work. No errors just always the add to cart button.
Updated: on April 21th, 2018
Woocommerce has a geolocation enabled tool (and WC_Geolocation related class) by default.
The first below uses that geolocation in a custom conditional function, where you will defined the related countries that are going to enabled your demo button.
In that function you will set all the related country codes in the array (I have defined 'US' and 'SG' just for testing purpose).
The code:
// Updated: check for the defined country codes based over user IP geolocation country code
function country_geo_ip_check(){
// ==> HERE define the countries codes in the array
$non_allowed_countries = array('US', 'SG');
// Get an instance of the WC_Geolocation object class
$geolocation_instance = new WC_Geolocation();
// Get user IP
$user_ip_address = $geolocation_instance->get_ip_address();
// Get geolocated user IP country code.
$user_geolocation = $geolocation_instance->geolocate_ip( $user_ip_address );
return in_array( $user_geolocation['country'], $non_allowed_countries ) ? false : true;
}
// Shop and other archives pages (replacing add to cart by a linked button to the product)
add_filter( 'woocommerce_loop_add_to_cart_link', 'replace_loop_add_to_cart_button', 10, 2 );
function replace_loop_add_to_cart_button( $button, $product ) {
if ( country_geo_ip_check() ) return $button; // Exit for non defined countries
if ( $product->is_type( 'variable' ) ) return $button; // Excluding variable products
$button_text = __( "View product", "woocommerce" );
$button_link = $product->get_permalink();
return '<a class="button" href="' . $button_link . '">' . $button_text . '</a>';;
}
// Single producct pages
add_action( 'woocommerce_single_product_summary', 'replace_single_add_to_cart_button', 1 );
function replace_single_add_to_cart_button() {
global $product;
if ( country_geo_ip_check() ) return; // Exit for non defined countries
// For variable product types (keeping attribute select fields)
if( $product->is_type( 'variable' ) ) {
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
add_action( 'woocommerce_single_product_summary', 'custom_demo_button', 20 );
}
// For all other product types
else {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary', 'custom_demo_button', 30 );
}
}
// Your custom button replacement
function custom_demo_button() {
global $post, $product;
$style = 'style="padding-right: 0.75em;padding-left: 0.75em;margin-left: 8px; background-color: #0ebc30;"';
$button_text = __("View Demo", "woocommerce");
// Get demo Url
if( function_exists('get_field') )
$url_demo = get_field( "url_demo" );
if( ! isset($url_demo) ){ // If the Url is not defined
$button_text = __("Missing URL", "woocommerce");
$style = 'style="color: red; background-color: white; border: solid 1px red"';
$url_demo = '#';
}
// Output
echo '<a href="'.$url_demo.'" target="_blank" class="button demo_button"'.$style.'>'.$button_text.'</a>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.