{"id":381195,"date":"2026-10-10T04:50:18","date_gmt":"2026-10-10T04:50:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/nubocoder-agency-manager\/"},"modified":"2026-10-10T04:49:59","modified_gmt":"2026-10-10T04:49:59","slug":"nubocoder-agency-manager","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/nubocoder-agency-manager\/","author":15363655,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.1.1","stable_tag":"0.1.1","tested":"7.1.3","requires":"6.9","requires_php":"8.1","requires_plugins":null,"header_name":"Nubocoder Agency Manager","header_author":"Nubocoder","header_description":"Manage the team accounts of every client site from one dashboard: give access to new team members, change roles and remove people who leave, on one site or all of them at once.","assets_banners_color":"","last_updated":"2026-10-10 04:49:59","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":57,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.1":{"tag":"0.1.1","author":"melkor1985","date":"2026-10-10 04:49:59","revision":3737587}},"upgrade_notice":[],"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.1.1"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[159171,5590,183004,3491,1917],"plugin_category":[58],"plugin_contributors":[212750],"plugin_business_model":[],"class_list":["post-381195","plugin","type-plugin","status-publish","hentry","plugin_tags-access-management","plugin_tags-agency","plugin_tags-multiple-sites","plugin_tags-team","plugin_tags-users","plugin_category-user-management","plugin_contributors-melkor1985","plugin_committers-melkor1985"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/nubocoder-agency-manager.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>When a developer or marketer joins an agency, they need an account on every client site. When they leave, every one of those accounts must go. Doing it site by site is slow and one forgotten account is a security risk.<\/p>\n\n<p>Agency Manager keeps your team in one place and applies it to your client sites:<\/p>\n\n<ul>\n<li>Define team members and teams (for example Developers or Marketing), each with the role it gets on client sites.<\/li>\n<li>Give access to one or many people on one, several or all sites, with a review of every change before anything is sent.<\/li>\n<li>Change roles, suspend, restore or remove accounts in bulk.<\/li>\n<li>Retire a member: every account is removed or suspended, and sites that do not answer are retried until it is done. Their content goes to an agency service account.<\/li>\n<li>See who has access to what in the access matrix, including accounts whose role was changed on the site and administrators not managed by the agency.<\/li>\n<li>Follow every change site by site, retry failures and read the tamper-evident activity log.<\/li>\n<\/ul>\n\n<p>Each client site needs the companion plugin Nubocoder Agency Manager Client.<\/p>\n\n<h4>Security<\/h4>\n\n<ul>\n<li>Every request to a client site is signed with a key pair dedicated to that site, is valid for five minutes and cannot be replayed. Responses are signed too.<\/li>\n<li>Site keys are encrypted in the database with the NBAM_ENCRYPTION_KEY constant.<\/li>\n<li>Client sites only let the agency change accounts it created; the site owner decides what the agency may do and can disconnect at any time.<\/li>\n<li>Removing access and granting administrator roles ask for your password again. The owner is emailed about critical actions.<\/li>\n<li>Dedicated capabilities, optional mandatory two-factor authentication and an emergency button that revokes every key.<\/li>\n<\/ul>\n\n<p>Install the hub on a dedicated WordPress site with few plugins, not on the public website of the agency.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin does not use any third-party service. It only talks to the client sites that you add in Agency Manager \u2192 Sites, which run the companion plugin Nubocoder Agency Manager Client. Nothing is sent until you add a site and its owner pastes the connection key on that site.<\/p>\n\n<ul>\n<li>When a client site connects, it sends its address, its REST endpoint, its public key and the client plugin version.<\/li>\n<li>To show and apply access, the hub sends signed requests to each connected site: the login, email, first and last name and role of the team members you give access to, and the role changes, suspensions and removals you confirm.<\/li>\n<li>Client sites answer with their WordPress and PHP versions, their name and address, their roles and number of users, and the login, email, role and post count of the accounts the agency manages there, plus the login, email and role of their administrators, so they appear in the access matrix.<\/li>\n<li>When you disconnect a site or use Revoke all, the hub tells that site to forget the connection.<\/li>\n<\/ul>\n\n<p>The data stays between your hub and your client sites. The hub also sends emails about critical actions through wp_mail() of your own site.<\/p>\n\n<h3>Third-party libraries<\/h3>\n\n<p>The plugin includes Action Scheduler (https:\/\/actionscheduler.org\/, GPLv3 or later) to run jobs in the background. The full source, including composer.json, is part of the plugin.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin on the agency WordPress site.<\/li>\n<li>Add define( 'NBAM_ENCRYPTION_KEY', '...' ); to wp-config.php. Agency Manager \u2192 Settings shows a ready to copy line.<\/li>\n<li>In Agency Manager \u2192 Sites, add a client site and copy its connection key.<\/li>\n<li>On the client site, install Nubocoder Agency Manager Client and paste the key in Settings \u2192 Agency Connection.<\/li>\n<li>Create your teams and members, then give access.<\/li>\n<\/ol>\n\n<p>For reliable background jobs, run WP-Cron from a server cron job and set DISABLE_WP_CRON.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20the%20hub%20store%20passwords%20of%20client%20sites%3F\"><h3>Does the hub store passwords of client sites?<\/h3><\/dt>\n<dd><p>No. New accounts get a random password and, if you choose, an email to set their own. The hub never receives passwords.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20posts%20of%20removed%20accounts%3F\"><h3>What happens to posts of removed accounts?<\/h3><\/dt>\n<dd><p>They are reassigned to the agency service account configured in Settings, created on each site with the Subscriber role.<\/p><\/dd>\n<dt id=\"can%20the%20agency%20delete%20accounts%20of%20the%20site%20owner%3F\"><h3>Can the agency delete accounts of the site owner?<\/h3><\/dt>\n<dd><p>No. The client plugin only changes accounts the agency created or linked, and never removes the last administrator.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>The Agency Manager menu now sits at the end of the admin menu instead of near the top.<\/li>\n<li>Deactivation removes the Action Scheduler WP-Cron event, so WP-Cron no longer logs an error for it afterwards.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>First release: sites, teams, members, access grants, role changes, suspension, removal, retirement, access matrix, jobs and activity log.<\/li>\n<\/ul>","raw_excerpt":"Give your agency team access to every client site from one dashboard, and remove it everywhere when someone leaves.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/381195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=381195"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/melkor1985"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=381195"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=381195"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=381195"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=381195"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=381195"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=381195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}