Getting Google Maps API’s to work with Advanced Custom Fields

Google map embeds have recently become a massive pain in the butt. You need api keys to embed them, which is fine but the documentation is seriously disjointed and overly complicated.

We use them a lot within our WordPress builds. We use the ACF Google Map field most of the time. Below are the steps to get the bloody things working.

  1. Go to the Google API dashboard here.
  2. Create a project.
  3. Enable an APIs by clicking on the Enable API button (see below).
    screen-shot-2017-01-24-at-11-56-16
  4. Select the API you want to enable from the library (see below)
    screen-shot-2017-01-24-at-11-58-39
  5. You will need to enable all the following APIs. By following the previous two steps for each API.
    1. Google Places API Web Service
    2. Google Maps JavaScript API
  6. Then create Credentials for the project by clicking on the credentials tab and then the Create Credentials button. Select API key from the dropdown. You will be given an API key.
    screen-shot-2017-01-24-at-12-02-01
  7. You then need to use that key wherever you are calling the Google Maps API for embedding the map. Use this format:
    https://maps.googleapis.com/maps/api/js?key=your-key-here&v=3.exp&sensor=false
  8. If you are using Advanced Custom Fields you also need to include a function within your functions.php file to make the backend work You can see how here: https://www.advancedcustomfields.com/resources/google-map/
    We use the below function as we are using ACF Pro.

    function my_acf_init() {
    	
    	acf_update_setting('google_api_key', 'xxx');
    }
    
    add_action('acf/init', 'my_acf_init');

If this isn’t working then make sure you check the console logs. They should tell you what APIs are not working. I may have missed some on the list in step 5 and just not run into a use case scenario where I have seen the error.

I hope this stops you getting in a tantrum and throwing your computer out the window. I had a numerous battles with this before I decided to write this down.

Advertisements

Add a post counter to each post that works with pagination

I needed to add an incrementing number to each post on an archive page within WordPress. The issue I was having was with pagination, the counter would be reset on each page.

To resolve this I had to get the posts per page and total posts and work out a formula for correctly setting my counter on each page.

<?php
$posts_per_page = get_option( 'posts_per_page' );
$total_posts = $GLOBALS['wp_query']->found_posts;
$total_pages = $posts_per_page / $total_posts;
$current_page = (get_query_var('paged')) ? get_query_var('paged') : 1;

if ( $current_page === 1 ) {
// On page 1 start at 1
$counter = 1;
} elseif ( $current_page === 2 ) {
// On page 2 start on the post per page + 1
$counter = $posts_per_page + 1;
} else {
// On other pages.
// For example on page 2 with 5 posts per page we want the counter to start on 6
// So page * posts per page - posts on the last page + 1 to get to this page = 6
$counter = ( $current_page * $posts_per_page - $posts_per_page + 1 );
} ?>

Thanks to the doc4design.com article for pointing me in the right direction.

Display custom post types from WordPress RSS feed as HTML

I was working on a RSS driven newsletter for a client that need to have a web page displaying all the posts from a custom post type using the WordPress RSS feed.

First I needed to get the correct feed URL. The feed URL for custom post types can be located using a query string in the URL:

http://your-wordpress-site.com/feed/?post_type=yourcustomposttype

Replacing the your-wordpress-site.com with the url of the site you will be getting the feed from. And change yourcustomposttype with the name of your custom post type.

See: https://codex.wordpress.org/WordPress_Feeds

We can then use PHP to load the feed in to an array and loop through each elements tag name and pull the values we need and echo them to the page:

<?php 

$url = 'http://your-wordpress-site.com/feed/?post_type=yourcustomposttype'; $rss = new DOMDocument(); $rss->load($url);
$feed = array();

foreach ($rss->getElementsByTagName('item') as $node) {
  
  $image = $node->getElementsByTagName('image')->item(0)->nodeValue;
  $title = $node->getElementsByTagName('title')->item(0)->nodeValue;
  $link = $node->getElementsByTagName('link')->item(0)->nodeValue;

  echo '<h1><a href="' . $link . '">' . $title . '</a></h1>';

} ?>

Big thanks to this question on stack over flow and several of the answers http://stackoverflow.com/questions/3346628/retrieving-rss-feed-with-tag-contentencoded

Get the Featured Image URL in WordPress

I looked for an elegant way to find the URL of a specific size of the Featured Image in WordPress for a while. This is a nice way:

Get Featured Image URL

Setting up .htaccess URL Redirects in WordPress

The correct way to setup redirects within the WordPress .htaccess file is to put your redirects above the WordPress pretty permalinks code like so:

# BEGIN Redirects

Redirect 301 /from-here/ http://www.domain.com/to-here

# END Redirects

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Scheduling a category change, based on an Advanced Custom Field value, when a post is saved using a WordPress CRON job

The problem:

We had a client’s website that had a custom post type called ‘Events’. We also had a category called ‘Past Events’. This category hid the Event from the Current Events page. When an event had passed our client had to go into the backend and put the Event into the ‘Past Events’ category. As the volume of Events increased this process became too time intensive.

We wanted to maintain the mechanism of using a category to hide them as we had used this in many loops throughout the site but we needed a way to make a past event automatically add to that category at a certain date.

In addition to this we needed the date to be set via a start date or optional end date field created with the brilliant Advanced Custom Fields Plugin.

So, in a nutshell we needed to change an individual post’s category on a given date (via an ACF field) sometime in the future.

The solution:

Overview

  1. Create a function that sets a WP Cron job to fire the day after an event ends
  2. Create or update that Cron job every time the post is saved (ie. created or edited)
  3. Create a function that puts the post into the past events category
  4. Run that function when the WP Cron job is fire

The code

The code solutions here are very well commented but I have not gone into detail about why I did certain things certain ways due to time. If there is interest in me doing this then please ask in the comments and I will find the time.

Create a function that sets a WP Cron job to fire the day after an event ends.

// Create a cron job to run the day after an event happens or ends
function set_expiry_date( $post_id ) {

  // See if an event_end_date or event_date has been entered and if not then end the function
  if( get_post_meta( $post_id, $key = 'event_end_date', $single = true ) ) {

    // Get the end date of the event in unix grenwich mean time
    $acf_end_date = get_post_meta( $post_id, $key = 'event_end_date', $single = true );

  } elseif ( get_post_meta( $post_id, $key = 'event_date', $single = true ) ) {

    // Get the start date of the event in unix grenwich mean time
    $acf_end_date = get_post_meta( $post_id, $key = 'event_date', $single = true );

  } else {

    // No start or end date. Lets delete any CRON jobs related to this post and end the function.
    wp_clear_scheduled_hook( 'make_past_event', array( $post_id ) );
    return;

  }

  // Convert our date to the correct format
  $unix_acf_end_date = strtotime( $acf_end_date );
  $gmt_end_date = gmdate( 'Ymd', $unix_acf_end_date );
  $unix_gmt_end_date = strtotime( $gmt_end_date );

  // Get the number of seconds in a day
  $delay = 24 * 60 * 60; //24 hours * 60 minutes * 60 seconds

  // Add 1 day to the end date to get the day after the event
  $day_after_event = $unix_gmt_end_date + $delay;

  // Temporarily remove from 'Past Event' category
  wp_remove_object_terms( $post_id, 'past-events', 'category' );

  // If a CRON job exists with this post_id them remove it
  wp_clear_scheduled_hook( 'make_past_event', array( $post_id ) );
  // Add the new CRON job to run the day after the event with the post_id as an argument
  wp_schedule_single_event( $day_after_event , 'make_past_event', array( $post_id ) );

}

Create or update that Cron job every time the post is saved (ie. created or edited)

// Hook into the save_post_{post-type} function to create/update the cron job everytime an event is saved.
add_action( 'acf/save_post', 'set_expiry_date', 20 );

Create a function that puts the post into the past events category

// Create a function that adds the post to the past-events category
function set_past_event_category( $post_id ){

  // Set the post category to 'Past Event'
  wp_set_post_categories( $post_id, array( 53 ), true );

}

Run that function when the WP Cron job is fire

// Hook into the make_past_event CRON job so that the set_past_event_category function runs when the CRON job is fired.
add_action( 'make_past_event', 'set_past_event_category' );

Resources

Good WP Cron job tutorial
http://www.smashingmagazine.com/2013/10/schedule-events-using-wordpress-cron/

ACF save_post function
http://www.advancedcustomfields.com/resources/acfsave_post/

A plugin used for debugging the CRON jobs
https://en-gb.wordpress.org/plugins/wp-crontrol/