Blog

Business Info Schema in Theme

Whenever putting together a website for a business, you often have to type the businesses information out throughout the website. Whether its the phone number or company address, if something ever needs to change, it can be a nightmare to try and replace all the instances that you (or they within posts) used the info. To get around this potential issue I like to define the generic company information on the back-end, and output it via shortcodes. To make it even better, we can utilize HTML5 schema microdata to define to “bots” what this information represents.

This is only for Genesis child themes ONLY. If you are not using Genesis, then this won’t work.

Our custom Genesis admin page
This is the page that is created on the back-end for you to enter your company details. Our short-codes will pull its information from these fields, and wrap the necessary schema around it when necessary.

 

Step 1: Create The Custom Admin Menu Item & Page

First, you need to add a page to the admin area where you can change and save your information. I like to keep this big chunk of code in its own file instead of just pasting it in my main functions. It just keeps things neat and organized that way. Although it should still work out fine if you wanted to paste it in your functions file.

Below is the code that:

  • Adds our custom menu item under the Genesis admin menu
  • Creates the admin page with the fields

[php]
‘parent_slug’ => ‘genesis’,
‘page_title’ => ‘Organization Information’,
‘menu_title’ => ‘Other Settings’,
‘capability’ => ‘manage_options’,
)
);

$page_ops = array(
‘screen_icon’ => ‘users’,
);

$settings_field = CHILD_SETTINGS_FIELD;

// Default values
$default_settings = array(
‘bpmtheme_office_phone’ => ”,
‘bpmtheme_company’ => ”,
‘bpmtheme_email’ => ”,
‘bpmtheme_fax’ => ”,
‘bpmtheme_street_address’ => ”,
‘bpmtheme_city’ => ”,
‘bpmtheme_state’ => ”,
‘bpmtheme_zip’ => ”,
‘bpmtheme_description’ => ”,

);

// Create
$this->create( $page_id, $menu_ops, $page_ops, $settings_field, $default_settings );

// Init sanitization
add_action( ‘genesis_settings_sanitizer_init’, array( $this, ‘sanitization_filters’ ) );

} // End contruct

// Set up Sanitization Filters
function sanitization_filters() {

genesis_add_option_filter( ‘no_html’, $this->settings_field,
array(
‘bpmtheme_office_phone’,
‘bpmtheme_email’,
‘bpmtheme_company’,
‘bpmtheme_fax’,
‘bpmtheme_street_address’,
‘bpmtheme_city’,
‘bpmtheme_state’,
‘bpmtheme_zip’,
‘bpmtheme_description’,
) );
}

function metaboxes() {
add_meta_box(‘contact-information’, ‘Contact Info’, array( $this, ‘bpmtheme_contact_information’ ), $this->pagehook, ‘main’, ‘high’);
}

function bpmtheme_contact_information() {

echo ‘

Enter your personal information here. This will be used site-wide and create shortcodes for

‘;

echo ‘

Company Name:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Office Phone:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Email:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Fax:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Street Address:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

City:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

State:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Zip:
‘;
echo ‘‘;
echo ‘

‘;

echo ‘

Description
‘;
echo ‘

‘;
}
}

function bpmtheme_add_child_theme_settings() {
global $_child_theme_settings;
$_child_theme_settings = new Child_Theme_Settings;
}

add_action( ‘admin_menu’, ‘bpmtheme_add_child_theme_settings’, 5 );
[/php]

Output Your Company Information – Enhanced With Schema Microdata

Next, lets create the shortcodes that will output our information. This way, you can use them throughout your theme and within your content.

[php]
function addScInfo($type) {

$phone = genesis_get_option( ‘bpmtheme_office_phone’, CHILD_SETTINGS_FIELD );
$email = genesis_get_option( ‘bpmtheme_email’, CHILD_SETTINGS_FIELD );
$fax = genesis_get_option( ‘bpmtheme_fax’, CHILD_SETTINGS_FIELD );
$street = genesis_get_option( ‘bpmtheme_street_address’, CHILD_SETTINGS_FIELD );
$city = genesis_get_option( ‘bpmtheme_city’, CHILD_SETTINGS_FIELD );
$state = genesis_get_option( ‘bpmtheme_state’, CHILD_SETTINGS_FIELD );
$zip = genesis_get_option( ‘bpmtheme_zip’, CHILD_SETTINGS_FIELD );
$companydescription = genesis_get_option( ‘bpmtheme_description’, CHILD_SETTINGS_FIELD );
$company = genesis_get_option( ‘bpmtheme_company’, CHILD_SETTINGS_FIELD );

extract(shortcode_atts(array(
‘type’ => ‘type’
), $type));

// check what type user entered
switch ($type) {
case ‘phone’:
return $phone;
break;
case ’email’:
return $email;
break;
case ‘all’:
return ‘

‘.$company.’

‘.esc_html($companydescription).’

‘.esc_html($street).’,
‘.esc_html($city).’, ‘.$state.’, ‘.esc_html($zip).’, US


Phone: ‘.esc_html($phone).’
Fax: ‘.esc_html($fax).’

‘;
break;
}
}
add_shortcode(‘info’, ‘addScInfo’);
[/php]

Usage

Use shortcodes to output the data you need – instead of manually typing the info out every time. Now if something changes, it changes everywhere.

Example:

[info type=”phone”] will output the phone number
[info type=”email”] will output the email address
[info type=”all”] will output the full company information – wrapped up nicely in schema. Search engines will appreciate and hopefully reward you.

If you want to use shortcodes in widgets, mane sure you have this filter in your functions

[php]
add_filter(‘widget_text’, ‘do_shortcode’);
[/php]

If you want to use shortcodes within a template(via php)

[php]
echo do_shortcode(‘[info type=”all”]’);
[/php]

Below is the output on the front-end when you use our new shortcodes.

Now you can use shortcodes to output pieces of information about your company. And again, if you ever need to change your phone number or address, you can simply change it in one spot and have it change site-wide. And its wrapped in schema!

Suggestions? Let me know!

Google Analytics Event Tracking Added Automatically With jQuery

Automatically add basic Google Analytics event tracking using jQuery. I wrote it for use on this site, but the script can be used as is or modified to suite your needs.

You can either:

  1. Add the code to an existing theme JavaScript file that is called on every page (or the pages you want to track events)
  2. Add the code to the footer of the every page before the closing body tag () (or the pages you want to track events)
  3. Download the script and include it on every page (..and again – or the pages you want to track events)

That’s it!

Then clicks will be automatically trigger a Google Analytics event on:

Other Outbound Links – Any other link that leaves your domain, but is not caught by the social media or affiliate match.

Outbound Affiliate Links – set as any link within your domain that includes “/go/”. You can alter to your liking by adjusting the match in the affilateLink variable. [code type=”js”]var affiliateLink = new RegExp(‘/go/+’);[/code]

Outbound Social Media Links – set as any outbound link that includes “Facebook, Twitter, Google+, Linkedin and Twitter”. You can change or adding or removing the names in the socialMedia variable. Make sure you seperate the values you want to match with a pipe “|” sign, and add them before the plus “+”. Case matters. [code type=”js”]var socialMedia = new RegExp(‘plus|linkedin|pinterest|facebook|twitter+’);[/code]

PDF Download Links – Any link that end in .pdf.
ZIP Download Links – Any link that ends in .zip
Anchor Text Links A link within your domain that includes a “#” sign, or a relative anchor link.

Any thoughts, feedback, or fixes would be appreciated.

Disclaimer: No guarantee! but it does work, I actively use both variations on sites

[code type=”js”]
jQuery(window).on(‘load’, function(){

var myWebsite = new RegExp(location.host);
var myWebsiteAnchor = new RegExp(‘#+’);
var badlinkJs = new RegExp(‘^javascript:+’);
var socialMedia = new RegExp(‘plus|linkedin|pinterest|facebook|twitter+’);
var affiliateLink = new RegExp(‘/go/+’);
var isDownloadPdf = new RegExp(‘.pdf$’);
var isDownloadzip = new RegExp(‘.zip$’);

jQuery(‘a’).each(function(){

var url = jQuery(this).attr(“href”);

if (badlinkJs.test(url)){
}
else if (affiliateLink.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Affiliate’, ‘”+ url +”‘]);”);
}
else if (socialMedia.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Social Media’, ‘”+ url +”‘]);”);
}
else if (myWebsiteAnchor.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Anchor’, ‘Click’, ‘”+ url +”‘]);”);
}
else if (! myWebsite.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Other’, ‘”+ url +”‘]);”);
}
else if (isDownloadzip.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Download’, ‘Zip’, ‘”+ url +”‘]);”);
}
else if (isDownloadPdf.test(url)){
jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Download’, ‘Pdf’, ‘”+ url +”‘]);”);
}
else { }

}); //End each function

}); //End window load function
[/code]

If you are using Google Analytics Universal, the code will be slightly different.

View below for UA event tracking
[code type=”js”]
jQuery(window).on(‘load’, function(){

var myWebsite = new RegExp(location.host);
var myWebsiteAnchor = new RegExp(‘#+’);
var badlinkJs = new RegExp(‘^javascript:+’);
var socialMedia = new RegExp(‘plus|linkedin|pinterest|facebook|twitter+’);
var affiliateLink = new RegExp(‘/go/+’);
var isDownloadPdf = new RegExp(‘.pdf$’);
var isDownloadzip = new RegExp(‘.zip$’);

jQuery(‘a’).each(function(){

var url = jQuery(this).attr(“href”);

if (badlinkJs.test(url)){
}
else if (affiliateLink.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘outbound’, ‘affiliate’, ‘”+ url +”‘]);”);
}
else if (socialMedia.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘outbound’, ‘social media’, ‘”+ url +”‘]);”);
}
else if (myWebsiteAnchor.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘anchor’, ‘click’, ‘”+ url +”‘]);”);
}
else if (! myWebsite.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘outbound’, ‘other’, ‘”+ url +”‘]);”);
}
else if (isDownloadzip.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘download’, ‘zip’, ‘”+url +”‘]);”);
}
else if (isDownloadPdf.test(url)){
jQuery(this).attr(“onclick”,”ga(‘send’, ‘event’, ‘download’, ‘pdf’, ‘”+ url +”‘]);”);
}
else { }

}); //End each function

}); //End window load function
[/code]

Or the compressed version:
[code type=”js”]
jQuery(window).on(“load”,function(){var d=new RegExp(location.host);var b=new RegExp(“#+”);var a=new RegExp(“^javascript:+”);var g=new RegExp(“plus|linkedin|pinterest|facebook|twitter+”);var e=new RegExp(“/go/+”);var c=new RegExp(“.pdf$”);var f=new RegExp(“.zip$”);jQuery(“a”).each(function(){var h=jQuery(this).attr(“href”);if(a.test(h)){}else{if(e.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Affiliate’, ‘”+h+”‘]);”)}else{if(g.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Social Media’, ‘”+h+”‘]);”)}else{if(b.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Anchor’, ‘Click’, ‘”+h+”‘]);”)}else{if(!d.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Outbound’, ‘Other’, ‘”+h+”‘]);”)}else{if(f.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Download’, ‘Zip’, ‘”+h+”‘]);”)}else{if(c.test(h)){jQuery(this).attr(“onclick”,”_gaq.push([‘_trackEvent’, ‘Download’, ‘Pdf’, ‘”+h+”‘]);”)}else{}}}}}}}})});
[/code]

Any thoughts? Anything you would change or add? Please let me know!

Marcus Hiles Wistia Shortcodes

marcus hiles wistia shortcodes banner

I’ve finally published my first plugin on WordPress.org! The plugin is called Marcus Hiles Wistia Shortcodes – and it gives people an easy way to add Wistia videos to their WordPress site using shortcodes.

You may be wondering why use shortcodes when you can just grab the embed code from within Wistia. The reason I created this plugin is to solve a few issues I was having with Wistia videos on my clients WordPress sites.

  • The editor would sometimes strip out the javascript files required to make the videos work
  • The editor would sometimes strip off the attributes on html wrappers that were required to make the videos work
  • We would often end up loading the wistia.js multiple times on a page if there was more than one video per page
  • We wanted a way to intelligently load all the scripts required by Wistia to make the videos work
  • Wistia has changed the embed code here and there, and we wanted consistency on how embeds were handled.

The Editor Breaks Wistia Embeds Sometimes

The content editor in WordPress does not like javascript, or non-standard html attributes. Whenever you save content, or switch back and forth between the visual and text editor, WP sanitizes the content. Unfortunately, this can remove things that you wanted there. To combat this, our first idea was to use a shortcode in-place of Wistia embeds. That way, the shortcode would act as a placeholder, where we could then – in code – inject the video in the right place.

Intelligently Loading Javascript

The embed code you copy from Wistia always includes the main wistia.js file. If you are copying multiple embed codes onto the same page, this leads to including this file multiple times within the page. Additionally, I’m not really a fan of having script tags randomly throughout the body of my document. It seems `hacky` and brittle. To resolve this, we use native WordPress functions like `wp_enqueue_scripts` and `wp_is_enqueued` to detect if the primary wistia js has loaded, and to load it only once, and also to group all the specific video .json files together right before the closing body tag.