A destination page that only says a beach is nearby becomes stale the moment conditions change. A small WordPress integration can turn that static page into a useful coastal decision layer by showing a beach record, its latest conditions, and a clear link to the full destination experience.
This tutorial uses the Beach Day API REST endpoints from a server-side WordPress shortcode. The important implementation choice is deliberate: keep the API key on the server, cache the response, and render only the fields your visitors need. That gives a tourism site, hotel site, or local guide a practical live-beach component without exposing a credential in browser JavaScript.
What you are building
The finished shortcode looks like this:
[beach_conditions beach_id="94"]
It requests the latest conditions for a known Beach Day API beach ID, caches the result for 30 minutes, and renders a compact panel. You can place it in a page, post, template, or reusable block.
Before connecting WordPress, use the Beach Day API docs to search for the beach you want. The tested API flow is:
GET /v1/beaches?search=Malibuto find matching beach records and IDs.GET /v1/beaches/{id}/conditionsto retrieve dated conditions for the selected record.- Render the most recent entry your product chooses to display.
Every API request except the health endpoint uses a Bearer token. Store it outside page content and outside client-side scripts.
1. Add the API key in wp-config.php
Add this line above the “That’s all, stop editing” comment in wp-config.php. Replace the placeholder locally. Do not paste a real key into a theme template, a Gutenberg block, or a public repository.
define('BEACH_DAY_API_KEY', 'replace-with-your-api-key');
For a more formal deployment, load the value from your hosting provider’s environment-variable settings and define the constant there. The essential rule is the same: the browser should never receive the token.
2. Add a server-side shortcode
Create a small site plugin or add the code to a child theme’s functions.php. A site plugin is usually the better home because the beach component should keep working if the design theme changes.
add_shortcode('beach_conditions', function ($atts) {
$atts = shortcode_atts([
'beach_id' => 0,
], $atts, 'beach_conditions');
$beach_id = absint($atts['beach_id']);
if (!$beach_id || !defined('BEACH_DAY_API_KEY')) {
return '';
}
$cache_key = 'beach_day_conditions_' . $beach_id;
$payload = get_transient($cache_key);
if (false === $payload) {
$response = wp_remote_get(
'https://beachdayapi.com/v1/beaches/' . $beach_id . '/conditions',
[
'timeout' => 12,
'headers' => [
'Authorization' => 'Bearer ' . BEACH_DAY_API_KEY,
'Accept' => 'application/json',
],
]
);
if (is_wp_error($response) || 200 !== wp_remote_retrieve_response_code($response)) {
return '<p>Beach conditions are temporarily unavailable.</p>';
}
$payload = json_decode(wp_remote_retrieve_body($response), true);
set_transient($cache_key, $payload, 30 * MINUTE_IN_SECONDS);
}
$latest = $payload['results'][0] ?? null;
if (!$latest) {
return '<p>No current conditions are available for this beach.</p>';
}
$weather = $latest['weather'] ?? [];
$ocean = $latest['ocean_conditions'] ?? [];
$water_quality = $latest['water_quality'] ?? [];
ob_start(); ?>
<section class="beach-conditions-card">
<h3>Latest beach conditions</h3>
<p><strong>Updated:</strong> <?php echo esc_html($latest['date'] ?? 'Not available'); ?></p>
<ul>
<li>Beach Day Score: <?php echo esc_html($latest['beach_day_score'] ?? 'Not available'); ?></li>
<li>Water quality: <?php echo esc_html($water_quality['grade'] ?? 'Not available'); ?></li>
<li>Air temperature: <?php echo esc_html($weather['temp_f'] ?? 'Not available'); ?>°F</li>
<li>Wave height: <?php echo esc_html($ocean['wave_height_ft'] ?? 'Not available'); ?> ft</li>
</ul>
</section>
<?php
return ob_get_clean();
});
The live endpoint returns a wrapper with a results array, so the shortcode explicitly selects results[0]. It also displays the returned date rather than labeling the output “live” without context. That small choice helps a visitor understand what the panel actually represents.
3. Decide which fields earn a place on the page
Do not turn a destination page into a raw JSON dump. Start with four or five fields that support a real visitor decision:
- Observation date: tells visitors when the returned record applies.
- Beach Day Score: a quick ranking or comparison input.
- Water-quality grade: useful health context, but not a substitute for showing advisory details when present.
- Air or water conditions: helpful for planning, particularly on a travel or local-guide page.
- Wave height or risk context: use this only when it serves the audience and label it carefully.
A good destination page makes the date, safety context, and conditions visible together. Avoid reducing the component to a single score or using one beach record to make a broad claim about an entire coastline.
4. Add a small amount of styling
Add this to your child theme stylesheet or the site’s additional CSS area. Keep the visual treatment quiet so the panel supports the page rather than competing with the booking, itinerary, or editorial content.
.beach-conditions-card {
max-width: 38rem;
margin: 1.5rem 0;
padding: 1.25rem;
border: 1px solid #d8e5e8;
border-radius: 12px;
background: #f7fbfc;
}
.beach-conditions-card h3 { margin-top: 0; }
.beach-conditions-card ul { margin-bottom: 0; }
5. Add a cache and failure policy before you scale
The transient in the example protects both page speed and API usage. On a low-traffic guide, 30 minutes is a reasonable starting point. On a high-traffic destination page, consider warming the cache with WordPress cron and serving the last successful record if a refresh fails.
Also decide what the page should do when there is no usable result. A blank panel is often better than displaying made-up defaults. If your editorial workflow needs a fallback, use copy such as “Conditions are currently unavailable” and preserve the rest of the destination page.
When a shortcode is enough, and when it is not
A shortcode is a strong first implementation for tourism guides, property websites, and editorial destinations. Move to a custom REST route, a block, or a server-rendered application component when you need multiple beach cards, location-aware search, more detailed advisory presentation, or product-specific ranking logic.
The same backend pattern still applies: search for the right beach record, retrieve dated conditions, cache responsibly, and show the narrow set of fields that helps a visitor make a better choice. See the tourism websites and city guides use case for product context, then review pricing when you are ready to scope production usage.
Start with one high-intent page
The best first WordPress deployment is usually one destination page that already attracts people deciding where to go. Add a small, dated beach-conditions panel, watch which fields your audience uses, and expand from there. Beach Day API gives the page beach-specific context that a location name and a generic weather widget cannot provide on their own.