WordPress Developer interview questions
100 real questions with model answers and explanations for WordPress Developer candidates.
See a WordPress Developer resume example →Practice with flashcards
Spaced repetition · Hunter Pass
Questions
I keep the main plugin file as a small composition root rather than the place where features are implemented.
- It defines the plugin header, guards direct access, and establishes path or version constants.
- It loads Composer's autoloader and wires service objects or hook registrars.
- It registers activation and deactivation callbacks from the main file, then delegates request-time work.
Why interviewers ask this: The interviewer checks whether you can separate WordPress discovery and wiring from feature code.
I use namespaces for PHP symbols and PSR-4 autoloading so classes map predictably to files.
- composer.json maps a vendor namespace such as Acme\Catalog to the src directory.
- The bootstrap requires vendor/autoload.php once instead of maintaining manual include chains.
- WordPress hook names, option keys, and global functions still need unique prefixes because namespaces do not cover them.
Why interviewers ask this: A strong answer distinguishes PHP symbol isolation from WordPress's global identifiers.
I split domain behavior, WordPress adapters, storage, and presentation instead of making one hook class own everything.
- Hook registrars translate WordPress actions or filters into calls on focused services.
- Repositories contain $wpdb or metadata access, while controllers handle REST or admin request contracts.
- Templates receive prepared view data and do not create queries or enforce business rules.
Why interviewers ask this: The interviewer evaluates whether the architecture has useful boundaries without unnecessary framework layers.
I check dependencies after plugins are loaded and before registering integration behavior.
- plugins_loaded is suitable for class or function availability because active plugins have been included by then.
- A dependency should be checked by a documented class, function, or API rather than only its directory name.
- If it is absent, the plugin should skip the integration and show an admin notice instead of causing a fatal error.
Why interviewers ask this: The interviewer checks lifecycle timing and whether optional integrations fail safely.
An activation callback runs as a one-time lifecycle operation, not as a normal fully initialized request.
- It should create schema or defaults idempotently and avoid assuming later hooks such as init have fired.
- If rewrite rules are needed, it must register the relevant structures before calling flush_rewrite_rules().
- The callback should not perform slow remote work or rely on output because activation may occur through admin, CLI, or network activation.
Why interviewers ask this: A strong answer understands activation context rather than treating it as an ordinary page load.
Deactivation stops temporary behavior, while uninstall may permanently remove owned data.
- Deactivation can unschedule cron events, release temporary resources, and flush changed rewrite rules.
- It normally preserves options, custom tables, and user content so reactivation is reversible.
- uninstall.php or register_uninstall_hook() may delete data after checking intent and any keep-data setting.
Why interviewers ask this: The interviewer checks whether you preserve user data across reversible lifecycle changes.
I put portable content behavior in a plugin and presentation tied to the active design in the theme.
- Post types, permissions, REST routes, and business rules should survive a theme switch.
- Templates, theme.json settings, patterns, and visual assets belong to the theme.
- A WooCommerce integration can keep pricing logic in a plugin while exposing theme templates or hooks for markup.
Why interviewers ask this: A strong answer bases the boundary on portability rather than file convenience.
after_setup_theme runs after the theme files load but early enough to declare theme capabilities.
- add_theme_support(), register_nav_menus(), and image sizes belong there rather than on init.
- A child theme's functions.php loads before the parent's, while callbacks on this hook can use priorities for deliberate ordering.
- Request-dependent work does not belong there because the main query has not been established.
Why interviewers ask this: The interviewer checks exact theme lifecycle timing and its consequences.
They mark dependency availability, theme setup, and general WordPress registration at different stages.
- plugins_loaded runs after active plugins are included, so plugin integrations can be wired there.
- after_setup_theme is for supports and theme-owned registrations after functions.php files load.
- init is later and suits post types, taxonomies, rewrite endpoints, and other request-wide registrations.
Why interviewers ask this: A strong answer maps work to lifecycle stages instead of using init for everything.
By wp, WordPress has parsed the request and built the main query, so query conditionals are meaningful.
- Functions such as is_singular() and is_archive() depend on the main WP_Query state.
- On init, post types exist but the requested object and conditional flags are not yet established.
- wp suits request-context decisions, while registration still belongs on earlier hooks.
Why interviewers ask this: The interviewer checks whether you know when WordPress conditionals become reliable.
I use template_redirect for redirects or response decisions after the query is known but before theme output.
- A redirect should call wp_safe_redirect() or wp_redirect() and then exit to prevent template output.
- Authentication gates and canonical redirects can inspect conditional tags at this stage.
- I do not include an alternative template there because template_include provides the proper filter contract.
Why interviewers ask this: A strong answer distinguishes response control from template selection.
template_include should return the final absolute template path without rendering it inside the callback.
- The incoming path is WordPress's hierarchy result and should remain the fallback.
- A plugin may replace it only for a narrowly matched request after confirming its template file exists.
- Because it is a filter, every branch must return a path and avoid echoing content.
Why interviewers ask this: The interviewer checks the late template selection contract and safe fallback behavior.
I register REST routes on rest_api_init with a namespace, path, methods, and explicit callbacks.
- The namespace should include a stable vendor and version such as acme/v1.
- methods can use WP_REST_Server constants, while callback receives a WP_REST_Request.
- permission_callback is required and should express access policy separately from input handling.
Why interviewers ask this: The interviewer checks whether you know the route lifecycle and complete endpoint contract.
The schema describes accepted input, validation rejects unacceptable values, and sanitization normalizes accepted ones.
- args can declare type, required, default, enum, and custom validate_callback or sanitize_callback.
- Validation should answer whether a value is allowed without silently changing its meaning.
- A sanitizer may trim or normalize a value, but the endpoint must still enforce domain rules in its service layer.
Why interviewers ask this: A strong answer separates documentation and shape checks from normalization and business rules.
It should return true for authorized requests or a WP_Error that explains the denied access.
- For protected content I normally check a capability such as current_user_can('edit_post', $post_id).
- Returning __return_true is appropriate only for intentionally public data, not as a way to silence registration warnings.
- Authentication establishes identity, while permission_callback decides whether that identity may perform this operation.
Why interviewers ask this: The interviewer checks whether you distinguish authentication from authorization.
A logged-in browser can use WordPress cookies, but state-changing REST requests also need a REST nonce.
- The client sends the wp_rest nonce in the X-WP-Nonce header, commonly through apiFetch middleware.
- WordPress verifies it to associate the request with the logged-in user and protect against CSRF.
- Without a valid nonce, cookie authentication is treated as unauthenticated rather than granting cookie privileges.
Why interviewers ask this: A strong answer connects cookies, the REST nonce, identity, and CSRF protection.
I return data or WP_REST_Response on success and WP_Error for expected failures.
- rest_ensure_response() normalizes arrays or objects into the REST response pipeline.
- WP_REST_Response lets the endpoint set status, headers, and links explicitly.
- WP_Error should carry a stable code, safe message, and status in error data so clients receive meaningful HTTP semantics.
Why interviewers ask this: The interviewer checks whether the endpoint follows WordPress and HTTP response contracts.
admin-ajax.php dispatches actions by the action request field and the user's login state.
- wp_ajax_{action} handles authenticated users.
- wp_ajax_nopriv_{action} must also be registered when logged-out visitors may call the feature.
- Both callbacks should terminate with wp_send_json_success(), wp_send_json_error(), or wp_die() rather than falling through.
Why interviewers ask this: The interviewer checks whether you know both AJAX hook families and their response lifecycle.
The nonce protects request intent, while the capability check protects authority.
- check_ajax_referer() rejects missing or invalid action-specific nonces and reduces CSRF risk.
- current_user_can() verifies that the current account may change the targeted resource.
- A valid nonce is not a role or permission and can be exposed to users who lack the requested capability.
Why interviewers ask this: A strong answer does not treat a nonce as authorization.
I prefer REST for a resource-oriented API with typed inputs and reusable HTTP semantics, and keep AJAX for narrow legacy integrations.
- REST provides route discovery, methods, schemas, permission callbacks, and standard status handling.
- It is easier to consume from React, external clients, or tests without encoding every operation as one action parameter.
- admin-ajax.php remains reasonable when an existing admin feature already uses its hooks and no reusable API is needed.
Why interviewers ask this: The interviewer evaluates technical judgment rather than expecting one mechanism to replace the other universally.
Locked questions
- 21
When is a custom table justified instead of posts, metadata, or options?
- 22
What does dbDelta() require from a CREATE TABLE statement?
- 23
How should a plugin manage versioned upgrades to its custom database schema?
databaseschemaplugins - 24
What return contracts matter when using $wpdb insert, update, and delete methods?
wpdb - 25
How should a plugin construct custom table names across installations?
plugins - 26
How should $wpdb->prepare() be used for values, lists, and LIKE patterns?
wpdb - 27
How do the main WP_Query and a secondary WP_Query differ?
wp-query - 28
How do nested meta_query relations work in WP_Query?
wp-query - 29
What should you know when combining tax_query clauses?
- 30
How do you order WP_Query results by numeric metadata or multiple criteria?
wp-query - 31
What are the key pagination contracts for WP_Query?
wp-querypagination - 32
How should pre_get_posts be scoped when changing an archive query?
queries - 33
How do Transients and the Object Cache differ?
caching - 34
What changes when Redis provides a persistent WordPress Object Cache?
cachingrediswordpress - 35
How should cache groups and misses be handled with wp_cache_get()?
caching - 36
Why is cache expiration not a complete invalidation strategy?
caching - 37
What role does block.json play in a custom Gutenberg block?
gutenberg - 38
How do generated asset metadata files support a block build?
- 39
How do edit, save, and block attributes relate in a Gutenberg block?
gutenberg - 40
When should a custom block use static versus dynamic rendering?
- 41
How does block context differ from ordinary block attributes?
- 42
How should a plugin handle text domains and translated placeholders?
plugins - 43
When do translation context and plural functions matter?
- 44
How do capabilities, roles, and meta capabilities differ?
capabilities - 45
What structure and context should a custom WP CLI command have?
- 46
Which WordPress database tables are per-site and which are network-wide in Multisite?
wordpressmultisitedatabase - 47
What contract must code follow when using switch_to_blog()?
- 48
How should network activation affect plugin setup and data scope?
activationplugins - 49
How do contextual escaping and prepared SQL solve different problems?
sqlescaping - 50
How should a WooCommerce extension use public APIs and hooks without owning checkout internals?
hookswoocommerceapi - 51
How would you implement a REST endpoint that lists upcoming events for a mobile client?
restendpoints - 52
How would you add a REST endpoint that lets editors update one event's venue?
restendpoints - 53
How would you build a Gutenberg block that always shows a selected WooCommerce product's current price?
gutenbergwoocommerce - 54
How would you implement a block that shows the next three events and stays current after publication?
- 55
How would you build a testimonial section where editors may add cards but cannot break each card's structure?
- 56
How would you keep editors from changing the layout of a campaign hero while still letting them replace its content?
- 57
How would you limit a news article template to approved editorial blocks?
- 58
How would you offer three approved hero designs without maintaining three separate blocks?
design - 59
A WordPress page became slow after a release; how would you diagnose it before changing code?
wordpress - 60
Query Monitor shows a page spending most of its time in database calls; how would you find the responsible code?
databasequeriesmonitoring - 61
A custom report query scans a large orders table; how would you decide what to optimize?
queriesoptimization - 62
How would you fix a slow query filtering by customer, status, and creation date?
querieshooks - 63
A product grid issues metadata queries for every card; how would you resolve it?
gridqueries - 64
An archive repeatedly loads terms and term metadata inside its loop; how would you optimize it?
optimization - 65
How would you audit a site where the autoloaded options payload has grown unusually large?
- 66
A plugin stores a large rarely used catalog in one autoloaded option; how would you change it safely?
plugins - 67
How would you cache an expensive availability calculation used on product pages?
caching - 68
How would you invalidate cached event lists when editors change an event?
caching - 69
An expired transient causes many simultaneous requests to call a slow API; how would you reduce the spike?
cachingapi - 70
How would you integrate a shipping quote API into checkout without making it fragile?
api - 71
A third-party API starts returning 429 responses; how would you resolve the integration behavior?
dependenciesapi - 72
How would you schedule a nightly supplier sync and prevent overlapping runs?
- 73
How would you secure and process inventory webhooks from a supplier?
webhooksconcurrency - 74
How would you deploy a plugin release from staging to production with minimal risk?
pluginsdeployment - 75
How would you prevent missing Composer or Gutenberg build files in a production release?
gutenberg - 76
How would you move selected content from staging to production with WP-CLI?
wp-cli - 77
How would you replace a staging domain in a WordPress database without corrupting serialized values?
serializationwordpressdatabase - 78
How would you migrate a WordPress site to a new HTTPS domain?
wordpresshttps - 79
How would you release a plugin update that adds columns and backfills existing rows?
backfillpluginsschema - 80
How would you make a database-changing plugin release safe to roll back?
databaserollbackplugins - 81
A plugin's hook callback runs before data from another plugin is ready; how would you resolve it?
hookspluginscallbacks - 82
A page loads two copies of the same JavaScript library; how would you diagnose and fix it?
javascript - 83
A filter intended for one product changes prices in admin reports and emails; how would you fix it?
hooks - 84
How would you audit a custom reporting plugin for SQL injection?
sqlinjectionplugins - 85
A plugin lets editors save promotional HTML that appears for visitors; how would you prevent stored XSS?
htmlxssplugins - 86
A search page prints the submitted query in its heading; how would you resolve a reflected XSS finding?
queriesxss - 87
An admin action deletes a booking by ID; how would you protect it from CSRF and unauthorized object access?
csrf - 88
How would you audit custom REST and AJAX handlers that expose customer data?
restajax - 89
A plugin fetches an image URL supplied by a user; how would you prevent SSRF?
plugins - 90
How would you secure a front-end document upload feature?
- 91
How would you implement a booking revenue report grouped by service category with custom $wpdb SQL?
sqlwpdb - 92
How would you add date filtering, sorting, and pagination to a custom customer report?
hookspaginationalgorithms - 93
How would you build a WooCommerce order export that remains compatible with HPOS?
woocommerce - 94
How would you send WooCommerce orders to a fulfillment API without duplicating shipments?
woocommerceapi - 95
A legacy WooCommerce plugin reads wp_posts for orders; how would you migrate it for HPOS?
pluginswoocommerce - 96
How would you test a plugin service that creates bookings and registers WordPress hooks?
wordpresshooksplugins - 97
How would you add TypeScript to a custom block plugin and keep its build reproducible?
reproducibilitytypescriptplugins - 98
How would you roll out a plugin update across a Multisite network and verify every site?
pluginsmultisite - 99
A scheduled import stopped running on a low-traffic site; how would you diagnose and resolve it?
- 100
A plugin update causes checkout errors in production; how would you resolve the incident and prepare the fix?
incidentsplugins