WP Manifestindependent plugin directory
manifest / admin / unbranded-handoff

Unbranded Handoff

White-label handoff mu-plugin for WordPress client sites: agency-branded login, quieter admin for clients

by Eduard · github.com/blademan/unbranded-handoff

★ 0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/blademan/unbranded-handoff/archive/refs/heads/main.zip

A small must-use plugin that makes a WordPress site feel like the agency's own product when it goes to a client.

v1.0.0. Tested locally on WordPress 7.1.2 (SQLite, PHP 8.5.11) with PHPCS clean. Run the checklist below on staging before using it on a production site.

What it does

For everyone (login screen):

  • Agency logo, link and link text instead of the WordPress ones.

For client users (any logged-in user who is not agency staff):

  • Removes risky capabilities: updates, plugin and theme install/edit/delete/activate, file editors.
  • Hides configured menus (default: Tools).
  • Removes the WordPress logo and update nodes from the admin bar.
  • Replaces the admin footer text with "Site by Agency" and hides the WordPress version.
  • Replaces the WordPress news dashboard widgets with a "Need help?" widget (name, support email, URL).

Agency staff see a normal WordPress admin.

Screenshots

Captured on a local test site with the sample config (agency "Example Studio").

Login screen (everyone)

Login screen with the agency logo instead of the WordPress logo

Agency user (unchanged admin) and client user (restricted admin)

Agency Client
Agency dashboard: standard WordPress admin with Plugins, Tools and news widgets Client dashboard: no WordPress logo, no Plugins or Tools, a Need help widget and a Site by footer

Direct URL as a client (for example plugin-editor.php) is blocked, not just hidden:

Client opening the plugin editor gets "Sorry, you are not allowed to access this page."

Requirements

  • WordPress 6.4+
  • PHP 8.2+

Install

  1. Copy unbranded-handoff.php and the unbranded-handoff/ folder into wp-content/mu-plugins/.
  2. Copy unbranded-handoff/config-sample.php to unbranded-handoff/config.php.
  3. Edit config.php: set your agency details and at least one of agency_email_domains or agency_user_ids.

Configuration

Key Type Purpose
agency_name string Shown on the login screen, footer and dashboard widget
agency_url URL Login logo link, footer link, dashboard widget
support_email email Dashboard widget
logo_url URL Login logo. Empty keeps the default
agency_email_domains string[] Users with these email domains are agency staff
agency_user_ids int[] User IDs that are agency staff
hidden_menus string[] Menu slugs hidden for clients (cosmetic)
restricted_caps string[] Capabilities removed from clients (real enforcement)

Decisions

  • Fail-safe. If both agency lists are empty, the plugin applies no restrictions and shows an admin notice. A bad config can never lock everyone out.
  • Removes, never grants. Agency status only exempts a user from restrictions. It never adds capabilities, so a user who registers with an agency email domain gains nothing.
  • Capabilities do the blocking, menus do not. Hiding a menu does not stop someone opening its URL. Removing the capability does, and also hides the menu and update nags for free. hidden_menus is only for extra cosmetic cleanup.
  • User-based, not constant-based. Restrictions use the user_has_cap filter and check the user being asked about, so cron, WP-CLI and REST requests behave the same as the browser.
  • Config file, not a settings screen. A settings page would be state-changing UI that needs nonces and its own attack surface. A file in version control per site is simpler and reviewable. A settings UI is a non-goal for v1.
  • No client names, no secrets. config.php is git-ignored. Do not put passwords or API keys in it.

Non-goals (v1)

Settings UI, multisite, page-builder-specific changes, and replacing the WordPress logo inside the admin.

Testing

Before using on a client site, on staging:

  1. Log in as an agency user: the admin looks unchanged.
  2. Log in as a client user: no update nags, no Plugins menu, no Tools menu, no theme/plugin editors (try /wp-admin/plugin-editor.php directly, expect "Sorry, you are not allowed").
  3. Log out: the login screen shows your logo and the logo link goes to your site.
  4. Empty both agency lists: the plugin shows the notice and applies no restrictions.

Development

composer install
composer lint

Code follows the WordPress coding standards, all globals use the ubc_ / UBC_ prefix.

License

MIT