Josh Morley WordPress, SEO and paid search

Skill · Web development

Development work I have been hired to do

This is the core of it. More than 2,400 paid development projects since 2015, rated 4.92 out of 5 by the clients who paid for them. Custom themes, custom plugins, WooCommerce, inherited codebases, broken sites, and the integrations that sit between WordPress and everything else.

A reviewer once said my "PHP code and CSS are well written and commented", which is the compliment I am proudest of, because it means the next developer could pick it up.

2,400+
Paid development projects delivered since 2015
4.92/5
Codeable rating across 2,523 rated projects
900+
Individual clients
47
Properties running through a reporting platform I built and maintain

What I am usually asked for

  • Custom themes and child themes, block themes and classic
  • Custom plugins and must-use plugins, including replacing plugins that have been abandoned
  • WooCommerce: checkout changes, custom fees, approval workflows, subscriptions, fulfilment integrations
  • Taking over code somebody else wrote, often with no documentation and no handover
  • REST, WP-CLI and direct database automation for work that is too large to do by hand
  • Third-party API integrations, in both directions
  • Multisite: building, maintaining and migrating networks
  • Work outside WordPress: React and TypeScript applications, Cloudflare Workers, D1

How I work

Audit before changing. On an inherited site I find out what is actually running, what version of everything, what has been hacked in, and what will break if I touch it.

Bulk operations get dry-run first, applied in a way that cannot half-complete, and verified by reading the data back afterwards. The verification is not optional, because a write can succeed while a cached response keeps serving the old value and makes it look like nothing happened.

And everything gets logged: what changed, which files, which database rows, what was deliberately left alone. If I disappeared tomorrow, the next developer could follow it.

Past jobs

Five development jobs and what happened

Client names withheld.

Client reporting platform, built from nothing

Full stack
Brief
Monthly reporting across dozens of client accounts was taking days, and the numbers were not consistent between clients because every report was assembled by hand.
What I did
Built a data pipeline that pulls Google Search Console, GA4, Ahrefs and WooCommerce for each client, normalises it into a versioned snapshot format, generates the commentary and comparison periods, and publishes a private per-client portal. Added validation so a snapshot with missing or stale source data says so on the page rather than quietly showing a misleading drop.
Result
Runs across 47 client properties. Reporting went from days a month to a command, and every figure is traceable to a dated snapshot file.

SEO dashboard on Cloudflare

React and TypeScript
Brief
A single place to see search performance, backlink data, commerce numbers and outstanding work per client, without logging into five platforms.
What I did
Built it as a React and TypeScript application on Cloudflare Pages with Cloudflare D1 behind it, and serverless functions wrapping the Search Console, Ahrefs, WooCommerce and GitHub APIs. Server-side credentials only, nothing sensitive in the browser.
Result
In use, with a monthly report generator on top of it. This site you are reading is also a Cloudflare Worker, for what it is worth.

WooCommerce checkout with approval and fees

WooCommerce
Brief
A breeder needed orders to be reviewed and approved before completion, with a handling fee applied conditionally at checkout. Neither behaviour existed in any plugin that fit.
What I did
Wrote it into the theme's functionality: conditional fee logic at checkout and an approval step in the order flow, with the emails and status transitions handled so the customer experience stayed coherent.
Result
A checkout that matches how the business actually sells, rather than the business changing how it sells to suit the plugin. Still running.

An SEO plugin that would not boot on a network

Custom plugin
Brief
On a multisite network, the SEO plugin's classes were failing to load on certain subsites. The admin screens worked, so the settings all looked correct, but the front end was shipping pages with no title tag, no meta description and no canonical.
What I did
Rather than fight the plugin, I wrote a must-use plugin that detects whether the SEO plugin actually booted and, if it did not, outputs a correct SEO head from the stored post meta. It now ships as standard in every subsite build on that network.
Result
Subsites that cannot silently go out with an empty head section, which is exactly the kind of failure nobody notices for three months.

Events migration into a custom-table calendar

Data migration
Brief
Bulk-import hundreds of events into a calendar plugin whose current version no longer stores event data in post meta.
What I did
Worked out that inserting the posts alone produces events that return a 404, because the plugin reads its own custom tables for dates and occurrences. Wrote the import to populate those tables alongside the posts, then verified by requesting every created URL.
Result
A working bulk import, and a documented gotcha that has saved me the same half-day twice since.

Craft

Things I learned the hard way and wrote down

A sample from my own notes. This is the real difference between fourteen years and two: not that I never hit these, but that I only hit each one once.

Never compose a URL from a post title

Pull the stored slug or ask WordPress for the permalink. Guessing from the title produces URLs that look right in a report and 404 in a browser.

Escape content before updating a post

The update function strips one layer of slashes, so passing unescaped block content silently destroys every unicode escape in it, which takes out every CSS custom property in the page.

A search and replace across all tables can eat your redirects

Run it without excluding the redirect table and you can flatten a source URL and its target into a redirect pointing at itself. The site then loops.

Assign product categories at creation

Create a WooCommerce product through the REST API without categories and it exists but vanishes from shop navigation. Set them in the create call.

Trust the front end, not the API response

A write can succeed while a cached read keeps returning the old value. Confirm with a cache-busted request to the actual page, and purge the edge as well as the object cache.

I keep notes like these per platform and per client. It is why the second time a client hits an obscure problem, it costs them twenty minutes instead of a day.

WordPress

PHP, custom themes and plugins, must-use plugins, block themes, ACF, WP REST API, WP-CLI, multisite, WPML and Polylang.

Commerce

WooCommerce and its extensions, Subscriptions, payment gateways, Printful and fulfilment integrations, Sensei LMS, LearnDash.

Beyond WordPress

JavaScript and TypeScript, React, Node, Python, Cloudflare Workers and Pages, D1, SQL, MySQL, Git.

Integrations

Google Search Console, GA4, Google Ads, Merchant Center, Ahrefs, Bing Webmaster Tools, Klaviyo, HubSpot, GoHighLevel, Zapier, Xero.

Reviews

Clients on the development work

When I asked WordPress engineers to fix the problems I was having with my WordPress dashboard and with tagDiv, they referred me to their vetted partner for such work, which is Codeable. It is through Codeable that I found Josh Morley, who has proven to be the perfect answer for resolving the problems I was having, and I highly recommend Josh for you, as well.
John Levay Codeable
Josh was easy to work with and understood my needs very well. I appreciate how quick he was to get this project done. His PHP code and CSS are well written and commented.
Frank G. Codeable
Terrific service. Great attention to detail, and he made sure the changes were tested and re-tested before signing the job off. I will definitely work with Josh again in the future.
Justin Hill Google
Josh stepped in at short notice and built the page we needed for a client contract in days. He was amazing. Thank you so much.
Lisa E. Codeable
Josh helped us out with a bespoke WordPress plugin. Very knowledgeable, professional, and pleasant dude to work with. Highly recommend.
Dr. David Tully CEO, Scenegraph Studios · LinkedIn
Josh helped me with a couple of tricky CSS issues on an eCommerce project. The communication was great, the quality of his work outstanding, prices are fair. Fully recommend!
Franz Sauerstein Ecommerce marketing consultant · LinkedIn
We had some accessibility issues that needed to be remediated on our website. Josh was incredibly easy to work with and very responsive. I was worried that I wouldn't be able to find anyone who could do a good job using Divi Theme and solve our remaining accessibility issues. Josh changed my perspective on that. I would definitely use his services again and highly recommend Josh for work on projects like this.
John B. Codeable
Josh is awesome! This is my second project with him and he never disappoints.
Maria C. Codeable
Great service, friendly, and very knowledgeable.
Mick C. Codeable

The rest of the skill set

Most jobs touch more than one of these. I can take the whole thing or just the part you are short of.

Contact

Tell me about the role or the job

Contract, part-time, one-off fix or white-label work for another agency: all fine. Say what you need and when you need it, and I will tell you honestly whether I am the right person for it.

Email
hello@josh-morley.com
Based
Liverpool, United Kingdom
Hours
10am to 5pm GMT
Reply
Within one business day
Languages
English (native)

Prefer to talk first? Book a discovery call, or download my CV.

You can also hire me through Codeable, where the rating, project count and reviews are all independently verifiable.

The more specific you are, the more useful my first reply will be.

Or email hello@josh-morley.com