[WP] Fully Customized User Management with ACF & Gravity Forms

The core idea of any interactive website is to respond to the user’s actions, which is performed with several steps: collecting inputs, processing then visualizing. Unfortunately, this could not be fully controlled/customized only with WordPress core.

ACF makes it much easier to expand WordPress functionalities, allows us to take full control of not only posts but users (and more…). GForms provides a security & convenient layer to collect user’s info.

By using hooks, you can build fully customized site’s functions like User Management* (login, register, logs,… – totally Front-End), Shopping Cart (easy implemented with cookies), User Thread New Post like Forums,  … in a secured & comfortable way, without having to use a bunch of additional plugins for each feature.


User Management is always a big disadvantage of using WordPress. This article will give you the solution to some key features such as Register Page, User Post Submit (both front-end), discussing issues about security and other ideas.

Front-End Login Form

If you are looking for a Front-End Login Page, WP provides:

$args = array(
	'redirect' => home_url(), 
	'form_id' => 'loginform-custom',
	'label_username' => __( 'Username' ),
	'label_password' => __( 'Password' ),
	'label_remember' => __( 'Remember Me' ),
	'label_log_in' => __( 'Log in' ),
	'remember' => true
wp_login_form( $args );

Or more: https://codex.wordpress.org/Function_Reference/wp_login_form

Now we can totally disable /wp-admin/ for those who are not admins (disable user’s back-end).
I picked up this code somewhere, forgive me not mentioning the source (I don’t remember): these lines use ‘admin_init‘ hook

function wpse66093_no_admin_access()
    $redirect = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : home_url( '/' );
    if ( !current_user_can( 'delete_users' ) )
        exit( wp_redirect( $redirect ) );
add_action( 'admin_init', 'wpse66093_no_admin_access', 100 );

For authorized /wp-admin/ access (for us), we use the login form to log in, then go /wp-admin/.

Custom Fields & Registration Form

Create Custom Fields

With ACF you can easily create User’s extra fields. Let’s say you created 2 more fields: ‘address‘, ‘phone_number‘ (You should choose “Rule” equal to “All” when creating new Field Group). These values are stored in user’s meta data table.

Create a Register Form

Create the form using GForms, remember required fields like ‘user_login‘ (username), ‘user_pass‘ & our 2 custom fields.
Below I used: (Created with GForms)
1. username
2. email
3. password
4. retype
5. address
6. phone_number

Reg Form Validation?

Now we face the problem to make sure that the chosen usernameemail are not used, and if you are careful enough to have created a “Retype Password” input in your reg form then this will be a problem.

We solve this by using GF hook ‘gform_validation‘, this is how we validate username.
My Reg Form Id is 2, so the hook name will be ‘gform_validation_2‘:

add_filter( 'gform_validation_2', 'validate_reg');
function validate_reg( $validation_result ) {
	$form = $validation_result['form'];
	$user_name = rgpost( "input_1" );
	if (username_exists($user_name)) {
		$form['fields']['1']['failed_validation'] = true;
		$form['fields']['1']['validation_message'] = 'Username invalid!';
		$validation_result['is_valid'] = false;
	$validation_result['form'] = $form;
	return $validation_result;

Same with other validations, we check email_exists(), rgpost( “input_3″ ) = rgpost( “input_4″ ), which field#3 and field#4 are password & retype.

Create new user

We use ‘gform_after_submission‘ hook. This is called after a successful submission.

add_action( 'gform_after_submission', 'gform_after_submit', 10, 2 );
function gform_after_submit( $entry, $form ) {
	if ($form['id'] == 2) { // that way, u can implement 'id' == 3, 4, ... below without anothor add_action
		$userdata = array(
			'user_login'  =>  $entry['1'],
			'user_email' => $entry['2'],
			'user_pass'   =>  $entry['3'],
			'last_name' => $entry['5']
		$user_id = wp_insert_user( $userdata ); // DONE
		if( !is_wp_error($user_id) ) {
			// Update meta for custom values
			update_user_meta($user_id, 'address', $entry['6'] );
			update_user_meta($user_id, 'phone_number', $entry['7'] );

It’s that easy!
Notice: Now you can (and should) DISABLE New User Registration in WordPress General Options. Our Reg Form will stay fine(due to our wp_insert_user() function)! Then put the reg form a Captcha or Recaptcha Field to prevent spamming.

Password Change Form

Same way with Registration Page. This time we change it directly when validating form.
Normally, I created 3 inputs (old one, new one and retype), my Form ID is 4, change ‘gform_validation_4‘ so it fit yours.

add_filter( 'gform_validation_4', 'validate_change_pwd');
function validate_change_pwd( $validation_result ) {
	$form = $validation_result['form'];
	$user_pwd = rgpost( "input_1" );
	$field_value1 = rgpost( "input_2" );
	$field_value2 = rgpost( "input_3" );
	if (!is_user_logged_in()) {
		return $validation_result;
	global $current_user;
	$user = get_user_by( 'login', $current_user->user_login );
	if (!$user || !wp_check_password( $user_pwd, $user->data->user_pass, $user->ID)) {
			$form['fields']['1']['failed_validation'] = true;
			$form['fields']['1']['validation_message'] = 'Password Incorrect!';
			$validation_result['is_valid'] = false;
	if ($field_value1!=$field_value2) {
			$form['fields']['2']['failed_validation'] = true;
			$form['fields']['2']['validation_message'] = 'Password mismatched!';
			$form['fields']['3']['failed_validation'] = true;
			$form['fields']['3']['validation_message'] = 'Password mismatched!';
			$validation_result['is_valid'] = false;
	if ($validation_result['is_valid'] == true) {
		wp_set_password($field_value1, $user->ID);
	$validation_result['form'] = $form;
    return $validation_result;

I believe with these ideas, we could get most of the site’s functions to work as we wish. I’ll be glad if you let me know what you’ve done.

I’ll write about user front-end posting in another article (basically with the same techniques we did above).

Leave a Reply