// === Google Reviews (ACF local group on Options) ===
add_action('acf/init', function () {
if( function_exists('acf_add_local_field_group') ){
acf_add_local_field_group([
'key' => 'group_spotts_google_reviews',
'title' => 'Footer: Google Reviews',
'fields' => [
[
'key' => 'field_gr_enable',
'label' => 'Enable Google Reviews',
'name' => 'gr_enable',
'type' => 'true_false',
'ui' => 1,
'default_value' => 0,
],
[
'key' => 'field_gr_title',
'label' => 'Section Title',
'name' => 'gr_title',
'type' => 'text',
'placeholder' => 'What clients say on Google',
],
[
'key' => 'field_gr_place_id',
'label' => 'Google Place ID',
'name' => 'gr_place_id',
'type' => 'text',
'instructions' => 'e.g. ChIJ... (Place ID for spottsgardens.com business)',
],
[
'key' => 'field_gr_api_key',
'label' => 'Google API Key (Places)',
'name' => 'gr_api_key',
'type' => 'text',
'instructions' => 'Must have Places API enabled. If left blank, the site-wide ACF Google key will NOT be used automatically—put a key here.',
],
[
'key' => 'field_gr_max',
'label' => 'Max Reviews to Show',
'name' => 'gr_max',
'type' => 'number',
'default_value' => 3,
'min' => 1,
'max' => 5
],
[
'key' => 'field_gr_min_rating',
'label' => 'Minimum Star Rating',
'name' => 'gr_min_rating',
'type' => 'number',
'default_value' => 4,
'min' => 1,
'max' => 5,
'step' => 0.1
],
],
'location' => [[[
'param' => 'options_page',
'operator' => '==',
'value' => 'acf-options',
]]],
]);
}
});
// === Fetch Google Reviews with caching ===
function spotts_get_google_reviews() {
if (!function_exists('get_field')) return [];
$enabled = get_field('gr_enable', 'options');
if (!$enabled) return [];
$place_id = trim((string) get_field('gr_place_id', 'options'));
$api_key = trim((string) get_field('gr_api_key', 'options'));
$max_show = (int) (get_field('gr_max', 'options') ?: 3);
$min_rating = (float) (get_field('gr_min_rating', 'options') ?: 4);
if (!$place_id || !$api_key) return [];
$transient_key = 'spotts_gr_' . md5($place_id . '|' . $max_show . '|' . $min_rating);
$cached = get_transient($transient_key);
if ($cached !== false) return $cached;
$endpoint = add_query_arg([
'place_id' => $place_id,
'fields' => 'name,url,rating,user_ratings_total,reviews',
'reviews_sort' => 'newest',
'key' => $api_key,
], 'https://maps.googleapis.com/maps/api/place/details/json');
$resp = wp_remote_get($endpoint, ['timeout' => 12]);
if (is_wp_error($resp)) return [];
$code = wp_remote_retrieve_response_code($resp);
if ($code !== 200) return [];
$data = json_decode(wp_remote_retrieve_body($resp), true);
if (!is_array($data) || empty($data['result'])) return [];
$result = $data['result'];
$reviews = isset($result['reviews']) && is_array($result['reviews']) ? $result['reviews'] : [];
// Filter & trim
$reviews = array_values(array_filter($reviews, function($r) use ($min_rating){
return isset($r['rating']) && (float)$r['rating'] >= $min_rating;
}));
$reviews = array_slice($reviews, 0, max(1, min(5, $max_show)));
// Normalize fields we need
$normalized = [];
foreach ($reviews as $r) {
$normalized[] = [
'author_name' => $r['author_name'] ?? 'Google User',
'profile_photo_url' => $r['profile_photo_url'] ?? '',
'rating' => (float) ($r['rating'] ?? 0),
'text' => $r['text'] ?? '',
'relative_time' => $r['relative_time_description'] ?? '',
'author_url' => $r['author_url'] ?? '',
'place_name' => $result['name'] ?? '',
'place_url' => $result['url'] ?? '',
'overall_rating' => (float) ($result['rating'] ?? 0),
'total_ratings' => (int) ($result['user_ratings_total'] ?? 0),
];
}
// Cache 12 hours
set_transient($transient_key, $normalized, 12 * HOUR_IN_SECONDS);
return $normalized;
}
Corey Morse - Spotts Garden Service
Please ensure Javascript is enabled for purposes of website accessibility
Corey Morse
Corey is an outgoing nature lover who has never met a stranger. He has years of experience with garden installations and is a certified registered technician in chemical applications. He sees his role at Spotts as connecting with people and then helping them connect with nature, and loves doing his part to keep Indianapolis cleaner, greener and healthier!