If you want your Fluent Forms WordPress form to automatically calculate travel distance based on a user’s postcode, and pass that distance to your emails or database, this step-by-step guide will help you set it up — using Google Maps Distance Matrix API for accurate distance calculation.


Why Use Google Maps Distance Matrix API?

Calculating the driving distance between two locations is tricky. The Google Maps Distance Matrix API provides accurate driving distances and durations between origins and destinations, perfect for travel cost estimations or delivery quotes.

What You'll Build

Step 1: Create Your Fluent Form

Make sure your form includes:

Step 2: Add JavaScript to Handle Postcode Blur Event

Here’s a sample JS snippet to send the postcode to the backend and update the distance field:

jQuery(document).ready(function($) {
if ($('#fluentform_6').length === 0) {
return;
}

const $submitBtn = $('#fluentform_6 .ff-btn-submit');
const $distanceField = $('#ff_6_travel_distance');

$submitBtn.prop('disabled', true);

$('#ff_6_address_zip_').on('blur', function() {
    const postcode = $(this).val().trim();
    if (!postcode) {
        $submitBtn.prop('disabled', true);
        return;
    }

    $.ajax({
        url: fluent_form_ajax.ajax_url,
        method: 'POST',
        data: {
            action: 'calculate_distance',
            postcode: postcode,
            security: fluent_form_ajax.nonce
        },
        success: function(response) {
            if(response.success) {
                const distanceValue = response.data.distance;

                $distanceField.val(distanceValue);

                const nativeInputEvent = new Event('input', { bubbles: true });
                $distanceField[0].dispatchEvent(nativeInputEvent);

                const nativeChangeEvent = new Event('change', { bubbles: true });
                $distanceField[0].dispatchEvent(nativeChangeEvent);

                $submitBtn.prop('disabled', false);
            } else {
                console.error('Distance calculation error:', response.data.message);
                $submitBtn.prop('disabled', true);
            }
        },
        error: function() {
            console.error('AJAX error calculating distance');
            $submitBtn.prop('disabled', true);
        }
    });
});

});

Step 3: Add PHP AJAX Handler with Google Maps API Integration

Add this code to your theme's functions.php or a custom plugin.

Make sure to replace 'YOUR_GOOGLE_MAPS_API_KEY' with your actual API key.

phpCopyEditadd_action('wp_ajax_calculate_distance', 'calculate_distance_callback');
add_action('wp_ajax_nopriv_calculate_distance', 'calculate_distance_callback');

function calculate_distance_callback() {
check_ajax_referer('fluent_form_nonce', 'security');

$postcode = sanitize_text_field($_POST['postcode'] ?? '');

if (empty($postcode)) {
wp_send_json_error(['message' => 'Postcode is required']);
}

$origin = '123 Main Street, Your City, Your Country'; // Change to your fixed origin address
$destination = $postcode;

$api_key = 'YOUR_GOOGLE_MAPS_API_KEY';

// Prepare Google Maps Distance Matrix API request
$url = add_query_arg([
'origins' => urlencode($origin),
'destinations' => urlencode($destination),
'key' => $api_key,
'units' => 'metric',
], 'https://maps.googleapis.com/maps/api/distancematrix/json');

$response = wp_remote_get($url);

if (is_wp_error($response)) {
wp_send_json_error(['message' => 'Failed to contact Google Maps API']);
}

$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);

if (!$data || $data['status'] !== 'OK') {
wp_send_json_error(['message' => 'Invalid response from Google Maps API']);
}

$elements = $data['rows'][0]['elements'][0] ?? null;

if (!$elements || $elements['status'] !== 'OK') {
wp_send_json_error(['message' => 'No route found to postcode']);
}

// Distance in meters -> convert to kilometers (or miles if you prefer)
$distance_meters = $elements['distance']['value'];
$distance_km = round($distance_meters / 1000, 2);

wp_send_json_success(['distance' => $distance_km]);
}


Step 4: Enqueue Scripts and Localize AJAX URL and Nonce

Add this code to enqueue jQuery and localize the AJAX endpoint and nonce:
<?php
add_action('wp_enqueue_scripts', function() {
if (is_singular()) {
global $post;

if (has_shortcode($post->post_content, 'fluentform') &&
(strpos($post->post_content, 'id="6"') !== false || strpos($post->post_content, 'id=6') !== false)) {

wp_enqueue_script('jquery');

wp_localize_script('jquery', 'fluent_form_ajax', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fluent_form_nonce'),
]);
}
}
});

Step 5: Test Your Form

  1. Go to your page with the form.
  2. Enter a postcode in the postcode field and move out of the input (blur event).
  3. The distance field should fill with the calculated distance from your fixed origin.
  4. The submit button becomes enabled.
  5. Submit the form.
  6. Check the received email or database entry to confirm the distance was submitted.

Complete Code Snippet from Github:

When building dynamic WordPress sites with Bricks Builder, there are times when you want to display posts related through a Meta Box relationship field, but also ensure there’s a fallback to show other posts of the same type if no relationships exist. This can be especially helpful for things like testimonials, related articles, or services.

In this post, I’ll walk you through a custom PHP query snippet that does exactly that: it fetches related posts via Meta Box’s relationship field and then fills in the rest of the results with other posts from the same post type — creating a seamless experience for the user and ensuring you never end up with an empty section.


The Goal

We want to:

  1. Query posts related to the current post via a Meta Box relationship field.
  2. Get all other posts of the same post type.
  3. Merge the two, showing related posts first, then fallback posts.

The Code

Here's the full query snippet:

phpCopyEdit$related = new WP_Query([
    'relationship' => [
        'id' => 'review-service',
        'to' => get_the_ID(),
    ],
    'nopaging' => true,
]);

$related_ids = wp_list_pluck($related->posts, 'ID');

$all = new WP_Query([
    'post_type' => 'testimonial',
    'posts_per_page' => -1,
    'fields' => 'ids',
]);

$other_ids = array_diff($all->posts, $related_ids);

return [
    'post_type' => 'testimonial',
    'post__in' => array_merge($related_ids, $other_ids),
    'orderby' => 'post__in',
    'posts_per_page' => -1,
];

Step-by-Step Explanation

1. Query Related Posts via Meta Box Relationship

phpCopyEdit$related = new WP_Query([
    'relationship' => [
        'id' => 'review-service',
        'to' => get_the_ID(),
    ],
    'nopaging' => true,
]);

2. Extract the IDs of Related Posts

phpCopyEdit$related_ids = wp_list_pluck($related->posts, 'ID');

3. Fetch All Testimonials

phpCopyEdit$all = new WP_Query([
    'post_type' => 'testimonial',
    'posts_per_page' => -1,
    'fields' => 'ids',
]);

4. Exclude Already Related Posts

phpCopyEdit$other_ids = array_diff($all->posts, $related_ids);

5. Merge & Return the Final Query

phpCopyEditreturn [
    'post_type' => 'testimonial',
    'post__in' => array_merge($related_ids, $other_ids),
    'orderby' => 'post__in',
    'posts_per_page' => -1,
];

Where to Use This in Bricks Builder

image

This code goes into a custom query in Bricks Builder:

  1. Select your Query Loop element (like a Repeater or Post element).
  2. Under the Query panel, choose "Custom PHP".
  3. Paste this snippet into the code area.

Make sure your Meta Box relationship field ID (review-service) and post type (testimonial) match your actual site setup.

Resources

Website no accessible after Apache update, due to a update conflicting with Plesk. Read the detailed article here.

How I Implemented an Image Comparison Slider in Bricks Builder

As a developer working with Bricks Builder, I'm always exploring creative ways to extend its capabilities. One limitation I've come across is the lack of a native image comparison element — something that's become increasingly useful for visual storytelling, particularly when showcasing before-and-after visuals in design or development workflows.

Fortunately, I found a sleek solution using a lightweight web component from sneas.io, and I’ve integrated it both statically and dynamically within Bricks. Here’s how I approached it.


Why Bricks Doesn’t Have This Natively

While Bricks Builder is incredibly flexible and powerful, it doesn’t (yet) ship with a built-in image comparison slider. Rather than relying on third-party plugins or heavy JavaScript libraries, I wanted a performant and minimal solution that could be implemented directly into my Bricks projects — ideally using native web components.


The Static Implementation

The quickest way to get an image comparison slider working is with a static embed. Here’s how I did it:

  1. Enable Code Execution in Bricks
    Ensure that the Bricks editor allows custom HTML/JS.
  2. Insert a Code Block
    In the Bricks editor, add a Code element and paste the following snippet: htmlCopyEdit<!-- Sourced from: https://img-comparison-slider.sneas.io/ --> <img-comparison-slider> <img slot="first" src="https://link-to-your-file" width="600" height="600"/> <img slot="second" src="link-to-your-file" width="600" height="600"/> </img-comparison-slider> <script defer src="https://unpkg.com/img-comparison-slider@7/dist/index.js"></script> This gives you a fully functional, static image comparison component right on the page.

The Dynamic Implementation (With Custom Fields)

For projects requiring dynamic content — such as client-managed before/after images — I took it a step further:

  1. Enable Code Execution
    As before, make sure custom code can be added safely in Bricks.
  2. Allow Custom HTML Tags
    By default, Bricks strips out unknown HTML tags. To use <img-comparison-slider>, we need to whitelist it. Add this to your functions.php: phpCopyEditadd_filter( 'bricks/allowed_html_tags', function( $allowed_html_tags ) { $additional_tags = ['img-comparison-slider']; return array_merge( $allowed_html_tags, $additional_tags ); } ); Official Bricks Docs
  3. Create the Structure in Bricks
    • Add a Custom HTML element and use the tag <img-comparison-slider>.
    • Inside this tag, add two image elements with dynamic data bindings: htmlCopyEdit<img slot="first" src="{YOUR_DYNAMIC_IMAGE_1}" /> <img slot="second" src="{YOUR_DYNAMIC_IMAGE_2}" />
    • Close the component with </img-comparison-slider>.
  4. Add the Script Block
    Below the comparison container, insert another code block with: htmlCopyEdit<script defer src="https://unpkg.com/img-comparison-slider@7/dist/index.js"></script> This ensures the slider component is properly loaded and functional on the front end.

This method lets me seamlessly integrate a performant and responsive image comparison slider into any Bricks layout — with support for both static and dynamic content. It's elegant, dependency-light, and makes full use of modern web standards.

If you've ever tried uploading a big file to your website and got hit with an annoying "file exceeds maximum upload size" error — you're not alone. I recently had to deal with this while working on one of my sites, and after a bit of digging, I found the simplest way to sort it out directly in Plesk, no server restarts or scary terminal commands needed.

So, let me show you exactly how I did it step by step, and how you can do it too.


Step 1: Head to Your Domain Dashboard

First things first:

  1. Log into your Plesk control panel.
  2. On the left, click Domains and pick the domain you're working on.
  3. Once you’re inside, go to the Dashboard tab of that domain — that’s where the magic happens.

Step 2: Tweak the PHP Settings

This is where you’ll increase the limit:

  1. Scroll down and click on PHP Settings.
  2. Find upload_max_filesize (you can search or just scroll through the list).
  3. Increase it to whatever you need — I usually go with something like 64M or 128M depending on the project.

Step 3: Don’t Forget post_max_size — It Caught Me Out!

Here's the bit that tripped me up the first time:
Simply changing upload_max_filesize isn't enough. There's another sneaky setting called post_max_size, and it must be larger than the upload limit, otherwise your new setting won’t even take effect.

For example:
If you set:

Think of post_max_size as the size of the whole package, and upload_max_filesize as the size of just the file inside. If the package is too small, it won't fit no matter what.


Step 4: Save and Apply

Once you've updated both values:

  1. Scroll down and hit OK or Apply.
  2. Plesk might suggest restarting PHP — if it does, go ahead and do it.

Step 5: Test It

Now, head back to your site, CMS, or wherever you upload files, and try again. You should now be able to upload much larger files without any errors. It feels like a small victory every time!


Final Tip

I personally like to give myself a little buffer — if I need 50MB uploads, I’ll set upload_max_filesize to 64M and post_max_size to 80M. Just helps avoid edge cases.


And that’s it! No more upload errors. Hope this helps save you the headache I had the first time I ran into it.

1. Check selected template on single post

Go to the Oxygen Section of the post that is displaying a 404 and check that the "Render Page Using Template field" Displays the template you set up for the page:

image

2. Check Template Display Condition

Got to: Oxygen > Template > {select your template}

Check in your section "WHERE DOES THIS TEMPLATE APPLY?" that the correct post type is selected. For Single Post Templates make sure you select your post type under the dropdown "Singular".

image

3. Resave Permalinks

Got to: Settings > Permalinks

Scroll down on the Permalinks page can click "Save Changes". This will resave permalinks for your new post type and replace old settings in your .htaccess file.

image

4. The usual Oxygen Builder troubleshooting steps

Isotropic has a good guide on troubleshooting Oxygen Builder:

1. Back up you website

2. Regenerate CSS (Oxygen > Settings > CSS Cache TAB )

image

2. Resign Shortcodes (Oxygen > Settings > Security TAB )

image

Still need help? Get in touch with me to get help with your oxygen builder project.

What's needed

Step-by-step setup

1. Set Up Your GitHub Repository

2. Deploy Your Site on Netlify

3. Connect Your Domain via Cloudflare

Your website is now live and hosted for free!

Advantages of your free website

Zero Hosting Fees – Unlike Wix or Squarespace, Netlify offers free hosting with no hidden costs.

Full Ownership – You control your files and can move or modify them anytime.

Improved Performance – Static websites can load faster and are more secure compared to CMS-based websites.

High Security – Static HTML sites are more secure that 

Scalability – Ideal for simple portfolios, landing pages, or business info pages.

Disadvantages & Limitations

⚠️ Limited to Static Sites – This setup is not suitable for dynamic content, blogs, or e-commerce sites.

⚠️ No Built-in CMS – The basic HTML site will not allow advanced content management.

⚠️ Technical Knowledge Required – Making edits requires basic knowledge of HTML & CSS, though tools like ChatGPT can assist. I do offer this service, if you are interested drop me a message.

Who Is This Ideal For?

This setup works best for:

If you need a cost-effective, low-maintenance website, this is a great solution!

Are you planning to build or revamp your business website and wondering whether to hire a freelancer or an agency?

As someone who has worked as both a freelancer and alongside agencies, I often help clients navigate this decision. Each option has its strengths and challenges, and understanding how they operate can make all the difference in choosing the right fit for your business.

Unfortunately there is no easy answer to this question but lets break it down together...

Knowing Your Needs

Before deciding whether to hire a freelancer or an agency, it’s essential to clarify exactly what you need from your website. This involves understanding two key areas: functional requirements and non-functional requirements.

Do You Even Need a Website?

Sometimes, your goals might not even require a full website. For instance:

Choosing the Right Technology

Once you’ve defined your needs, you can research the best technologies to achieve your goals. Some popular options include:

Finding the Right Specialist

Having a clear understanding of your requirements will make it easier to find a specialist freelancer or agency in the right field. A freelancer with expertise in WordPress might be perfect for a small business blog, while an agency with a dedicated team could be better suited for building a complex e-commerce platform or custom web app.

The more detailed your brief, the easier it will be to match your project with the right professional.


How Freelancers Operate

Freelancers are independent professionals who work on a project-by-project basis. Their operating style tends to be more flexible and personalised, often offering a close, one-on-one working relationship.

Key Characteristics of Freelancers:

Drawbacks of Freelancers:

How Agencies Operate

Agencies are businesses with a team of professionals offering a wide range of services under one roof. They typically have structured processes and work collaboratively to complete projects.

Key Characteristics of Agencies:

Drawbacks of Agencies:


Pros and Cons of Hiring a Freelancer

Pros:

  1. Cost-Effectiveness: Freelancers are typically more affordable than agencies, as they don’t have the overheads of a team or office space.
  2. Flexibility: Working with a freelancer often allows for a more personal relationship and a customised approach to your project.
  3. Specialisation: Many freelancers focus on specific niches or skills, offering expertise in areas like WordPress, SEO, or e-commerce.

Cons:

  1. Limited Capacity: Freelancers may struggle to handle large or complex projects requiring multiple disciplines.
  2. Availability Risks: If your freelancer is unavailable or unresponsive, your project may face delays.
  3. Support Challenges: Freelancers may not provide consistent ongoing support or have the capacity for long-term maintenance.

Pros and Cons of Hiring an Agency

Pros

  1. Team Collaboration: Agencies bring together experts in design, development, marketing, and strategy, ensuring a well-rounded approach.
  2. Scalability: With more resources, agencies can handle large-scale or complex projects and adapt to tight deadlines or additional requirements.
  3. Reliability: Agencies often have dedicated project managers and established processes, making them a dependable choice for long-term support.

Cons:

  1. Higher Costs: Agencies charge premium prices to cover their overheads, team salaries, and administrative expenses.
  2. Less Personalised Service: With multiple clients, agencies may offer less one-on-one attention compared to freelancers.
  3. Possible Bureaucracy: Structured workflows and internal processes can lead to longer turnaround times or less flexibility.


Hybrid Solutions: Best of Both Worlds

In some cases, combining the strengths of both a freelancer and an agency can provide the ideal solution for your website needs. A hybrid approach allows businesses to tap into the specific strengths of both options, creating a balanced and cost-effective strategy.

Scenarios for Combining Freelancers and Agencies:

Transitioning from Freelancer-Built Websites to Agency Support:

As your business grows, your website’s needs may become more complex and demanding. Here’s how you can smoothly transition:

  1. Gradual Expansion: If you started with a freelancer for the initial website build, you can start involving an agency when your project requires more scalability, such as adding new features or increasing traffic.
  2. Ongoing Support: Initially, freelancers might handle updates or small tweaks, but as your business scales, an agency can take over full-site maintenance, ensuring consistent performance and security.
  3. Strategic Development: As your business evolves, you may want to expand your online presence with additional marketing or technology needs. Agencies can offer a broader range of services, including integrated marketing campaigns, advanced SEO strategies, and more robust tech infrastructure, which can be challenging for a freelancer alone to manage.

By blending the strengths of freelancers and agencies, you can create a more flexible and scalable solution that adapts to your growing needs.


Finding the Best Solution for Your Business

Choosing the right approach—whether a freelancer, agency, or hybrid—depends on the specific needs of your business and the scale of your website project. Here’s a quick guide to help you decide:

1. Start with Your Goals and Budget

2. Consider Future Growth

3. Evaluate Your In-House Capabilities

If you already have a team or some technical expertise, a freelancer might be enough to cover specific areas like design or content creation. However, if you lack in-house resources, an agency can provide a more comprehensive service, from design to strategy, development, and maintenance.

4. Long-Term Relationship and Support

Consider the level of ongoing support you require. Freelancers can be ideal for short-term, specific tasks, but if your business demands continuous updates, performance optimisation, or customer service, an agency with dedicated resources may offer the reliability and consistency you need.

I recently came across an issue where I was trying to use an advanced image field from Meta Box inside an Oxygen Builder repeater. However, after I selected the dynamic data values in Oxygen the field was not displaying. Oxygen Builder support made clear that this was an existing issue and that it needed a workaround as they did not know when it would get fixed.

Therefore I thought I might share my solution here in a step-by-step tutorial in case you are having the same issue.

Create the Meta Box Pro fields

1. Create a Meta Box Pro ‘group’ field for your post type

Make sure the ‘Group’ field is clonable, this allows you to populate the filed group on the post.

2. Create an ‘Image Advanced’ field

Once you have created the Group field in step one you need to add an ‘Image Advanced’  inside the Meta Box Group field. Remember the ID you named the ‘Advanced Image’ field. In our example, the id is 'section_image'.

Add the custom code

According to Oxygen support, you can use global ‘$meta_box_current_group_fields;’ to get the current group inside the Oxygen Repeater.

Therefore I created the following function and added it with the Code Snippets plugin to the functions.pho: 

function get_oxygen_repeater_section_image_id() {

    global $meta_box_current_group_fields;

    // Get the image ID

    // Replace ‘section_image’ with your image ID

    $image_id = $meta_box_current_group_fields['section_image'][0];

    return $image_id;

}

Make sure you replace the image ID ‘section_image’ with your own image ID. Once you are done save and activate the snippet. 

Query the image ID in the oxygen repeater

Set up the repeater

Select ‘Query’ in the repeater settings, tick the ‘Use Meta Box Group’ box and select your Meta Box Group field below.

select meta box aio group field in oxygen builder
select meta box aio group field in oxygen builder

Add the image element

Drag the image element inside the repeater element. Select ‘Media Library’ in the primary settings of the image element.

Query the image ID

  1. Select the ‘data’ option inside the ID field. 
    add dynamic meta box data to oxygen repeater
  2. Select ‘PHP Function Return value’ and the advanced dynamic data settings
    select ‘php function return value’ und the advanced dynamic data settings
  3. Insert the name of the function we previously created: ‘get_oxygen_repeater_section_image_id’
    enter function name calling meta box aio field

Save your edits, clear the cache and reload the page. The image from your Meta box group field should display now.

This article explains why the oxygen menu items does not wrap it's children into a new row when they are overflowing the screen. To understand this article you will require a basic understanding on flex-box. You can watch this video by Kevin Powell or read about flexbox on the MDN Docs.

The 'issue' with the native menu in oxygen

The Oxygen menu's ol element is set up as a flex-box, but does not contain a 'flex-wrap:wrap', which allows flex elements that would horizontally overflow

  1. Create a stylesheet in Oxygen Builder
  2. Add this code to your style sheet:

  3. /*Target ul selector of the relevant menu class swap .menu--footer for relevant menu class or #selector*/
    .menu--footer ul {
    flex-wrap:wrap;
    }

    /*Target li selector withing the list targeted above swap .menu--footer for relevant menu class or #selector*/
    .menu--footer ul li{
    width: fit-content !important;
    }
  4. Apply the class '.menu--footer' to your menu element in the Oxygen editor
responsive horizontal oxygen builder navigation menu
responsive horizontal oxygen builder navigation menu
/*Replace .menu with your menu class*/
.menu--footer ul {
flex-wrap:wrap;
}


.menu--footer ul li{
width: fit-content !important;
}

Start your project today

Get in touch
Contact Form
crosschevron-left