My requirement is to add couple of custom fields in the add/edit a site forms without touching the WordPress core. I tried to copy the site-new.php from /wp-admin/network and paste it into my custom plugin but it fails due to many dependencies. I dont think so it is good exercise to copy and paste the whole network folder inside the plugin.

I also tried to callout this hook but instead of override, it just show me the fields underneath of the form. I guess I need to add hook when users submit the form. but couldn't find the hook that I need to callout to save additional fields data in DB.

 add_action('network_site_new_form',  array($this, 'add_extra_new_site_fields'));

Added this function

function add_extra_new_site_fields()
    <form method="post" action="<?php echo network_admin_url( 'site-new.php?action=add-site' ); ?>" novalidate="novalidate">
        <?php wp_nonce_field( 'add-blog', '_wpnonce_add-blog' ); ?>
        <table class="form-table" role="presentation">
            <tr class="form-field form-required">
                <th scope="row"><label for="site-address"><?php _e( 'Site s Address (URL)' ); ?> <span class="required">*</span></label></th>
                    <?php if ( is_subdomain_install() ) { ?>
                        <input name="blog[domain]" type="text" class="regular-text" id="site-address" aria-describedby="site-address-desc" autocapitalize="none" autocorrect="off" required /><span class="no-break">.<?php echo preg_replace( '|^www\.|', '', get_network()->domain ); ?></span>
                    } else {
                        echo get_network()->domain . get_network()->path
                        <input name="blog[domain]" type="text" class="regular-text" id="site-address" aria-describedby="site-address-desc" autocapitalize="none" autocorrect="off" required />
                    echo '<p class="description" id="site-address-desc">' . __( 'Only lowercase letters (a-z), numbers, and hyphens are allowed.' ) . '</p>';
            <tr class="form-field form-required">
                <th scope="row"><label for="site-title"><?php _e( 'Site Title' ); ?> <span class="required">*</span></label></th>
                <td><input name="blog[title]" type="text" class="regular-text" id="site-title" required /></td>
            $languages    = get_available_languages();
            $translations = wp_get_available_translations();
            if ( ! empty( $languages ) || ! empty( $translations ) ) :
                <tr class="form-field form-required">
                    <th scope="row"><label for="site-language"><?php _e( 'Site Language' ); ?></label></th>
                        // Network default.
                        $lang = get_site_option( 'WPLANG' );

                        // Use English if the default isn't available.
                        if ( ! in_array( $lang, $languages ) ) {
                            $lang = '';

                                'name'                        => 'WPLANG',
                                'id'                          => 'site-language',
                                'selected'                    => $lang,
                                'languages'                   => $languages,
                                'translations'                => $translations,
                                //'show_available_translations' => current_user_can( 'install_languages' ) && wp_can_install_language_pack(),
            <?php endif; // Languages. ?>
            <tr class="form-field form-required">
                <th scope="row"><label for="admin-email"><?php _e( 'Admin Email' ); ?> <span class="required">*</span></label></th>
                <td><input name="blog[email]" type="email" class="regular-text wp-suggest-user" id="admin-email" data-autocomplete-type="search" data-autocomplete-field="user_email" aria-describedby="site-admin-email" required /></td>
            <tr class="form-field">
                <td colspan="2" class="td-full"><p id="site-admin-email"><?php _e( 'A new user will be created if the above email address is not in the database.' ); ?><br /><?php _e( 'The username and a link to set the password will be mailed to this email address.' ); ?></p></td>
            <tr class="form-field form-required">
                <th scope="row"><label for="admin-email"><?php _e( 'Account ID' ); ?> <span class="required">*</span></label></th>
                <td><input name="blog[account_id]" type="input" class="regular-text" id="admin-account_id" required /></td>

         * Fires at the end of the new site form in network admin.
         * @since 4.5.0
        //do_action( 'network_site_new_form' );

        submit_button( __( 'Add Site' ), 'primary', 'add-site' );

give me your suggestions.

  • I don't think adding fields is possible without replacing the entire form with a custom one
    – Tom J Nowell
    Aug 25, 2020 at 15:44
  • I added the whole form in the function in custom plugin. but it loads 2 forms which seems this function add_action('network_site_new_form' .. does not override the form. Aug 25, 2020 at 15:58
  • @TomJNowell it seems do_action( 'network_site_new_form' ) fires at the end of the new site form in network admin. I updated my post by adding the function of custom plugin. Aug 25, 2020 at 16:00
  • Yeah the only time I've seen it done is when the entire page is removed from the admin menu and a new page with a new form is added. Modiifying the pages of the network admin isn't well supported
    – Tom J Nowell
    Aug 25, 2020 at 16:25
  • @TomJNowell I am trying to add only the custom fields through add_extra_new_site_fields() but I need to add a hook ie: add_action( 'add-site', array($this, 'save_extra_new_site_action')); that gonna callout once a user submits the form. But this hook doesn't callout. Maybe I can not calling it the correct way. What do you think? Aug 25, 2020 at 16:35

1 Answer 1


Adding Markup To The Add New Site Form

You can add HTML markup to that form like this:

    function() {
        <p>Hello World</p>

enter image description here

Adding Markup To The Edit Site Forms

No. This cannot be done via PHP.

For the site edit info screen, no hooks exist to do this.

However, you might be able to add a new tab however via the network_edit_site_nav_links filter, allowing you to create a custom network admin page that's passed the site ID as a URL parameter. However you would need to recreate the tabs via network_edit_site_nav and do all the saving and displaying yourself.

What About Saving Extra Inputs When Creating a Site?

Sort of..

  • No dedicated hook is available to save those fields
  • The hook for adding the HTML is not a part of the table the existing fields are in, they will not be aligned
  • There is a hook for before and after a user is created if no user exists with the chosen administrator email, but it happens before the site is created

You can use the wp_insert_site hook to do work on the site after its creation, however you should check your fields are present, it may not even be a web request, or the network admin:

do_action( 'wp_insert_site', $new_site );

Also be wary, WP will be in installation mode when this happens, things that are normally available may not be available. What those things are is unclear.

My advice is don't do this. The best way to customize areas of the network admin, is to remove them completely, then re-implement them using brand new network admin pages via the admin menu API.

The network admin APIs weren't intended for extension, and the network admin was not built to be extensible in the way's you're wanting. Something that would normally be trivial to develop should be considered top tier super hard.

Additionally, even if you could store those values, there is no UI for viewing them, and the existing UI's cannot be extended. You will have to build it from scratch.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.