Support » Plugin: WP Fusion Lite » Filter data not synced

  • Resolved roadsunknown

    (@roadsunknown)


    Hi,

    I have several filters applied to user data on new user and update user. However, WP Fusion is not syncing the filtered data, rather the raw submitted form data. I debugged to trace the process and confirmed 1) the filters are being applied correctly and 2) the meta data is saving to database, prior to the execution of the WP Fusion sync functions.

    Here are two WordPress core filters (wp-includes/user.php:wp_insert_user()):

    1715: apply_filters( ‘pre_user_first_name’, $first_name )
    1726: apply_filters( ‘pre_user_last_name’, $last_name )

    https://developer.wordpress.org/reference/hooks/pre_user_first_name/
    https://developer.wordpress.org/reference/hooks/pre_user_last_name/

    (I have also tested with a third-party user profile plugin and associated filters, but for the sake of this example I opted to use core filters as to show there is not a plugin conflict/error. WP Fusion also ignores the user data filtered and syncs the unfiltered form $REQUEST or $POST data instead.)

    To recreate the issue:

    1) Add a filter to the functions file (or elsewhere). This is mine:

    function format_first_name($first_name) {
    $first_name = (ctype_upper(str_replace(‘ ‘, ”, $first_name)) ? ucwords(strtolower($first_name)) : ucwords($first_name));
    return $first_name;
    }
    add_filter(‘pre_user_first_name’, ‘format_first_name’, 10, 1);

    2) Edit a user, changing the value of the First Name (bob) and Last Name (jones) to all lowercase, e.g. bob jones.
    3) Save the user.
    4) Check WP Fusion log (and confirm in CRM).

    Actual Result: first_name and last_name data synced matches the raw form data submitted, e.g. bob jones.

    Expected Result: first_name and last_name are filtered (per example #1) to apply uppercase to first letter of names, e.g. Bob Jones.

    You can use any filter, this is my real world example: formatting poorly typed names.

    ** The same issue occurs with user_email using raw form data rather than filtered.

    For this use case, I am syncing to HubSpot but I believe this affects all contact sync integrations per includes/class-user.php:profile_update():257.

    For purposes of this debug, I focused on updating existing users but the issue also occurs with creating new users.

Viewing 4 replies - 1 through 4 (of 4 total)
  • Plugin Author verygoodplugins

    (@verygoodplugins)

    Hey @roadsunknown ,

    That’s an interesting issue. Thanks for bringing it up.

    Yes we do sync the unfiltered $_POST data during a profile update. That ended up giving us the best compatibility with other plugins, as we don’t always know where the profile_update is being triggered from, and whether or not the POST’ed values have been saved to the database yet.

    But I can see how that doesn’t work for your scenario.

    What I’ve done is in the push_user_meta() function in WPF_User I’ve added

    foreach ( $user_meta as $field => $value ) {
    	$user_meta[ $field ] = apply_filters( "pre_user_{$field}", $value );
    }

    so that any data being sent to the CRM will be passed through the pre_user_ filter. That’s working now with your pre_user_first_name example.

    I think that will be reliable… Unless you can think of a better idea?

    Hi @verygoodplugins. I understand why you use unfiltered to optimize compatibility. Using this method however would mean any other custom filters applied by any other plugin would not be compatible.

    It’s a compromise but I can work with it for my use case since WordPress core does provide pre_ filters for the fields I need before sync: first_name, last_name and user_email. (I do apply filters to other fields but in my use case I do not sync these.)

    https://developer.wordpress.org/reference/hooks/pre_user_email/

    Alternatively, checking if matches database and/or sync after save to database for new users via https://developer.wordpress.org/reference/hooks/user_register/ or updated users: https://developer.wordpress.org/reference/hooks/profile_update/ (which there is reference too but is removed?).

    Thanks for the help.

    Plugin Author verygoodplugins

    (@verygoodplugins)

    Hey @roadsunknown ,

    Well… it’s an interesting problem. I’m not sure our solution is the best one.

    We do actually hook into profile_update: https://github.com/verygoodplugins/wp-fusion-lite/blob/master/includes/class-user.php#L249. But it doesn’t tell us which fields were updated.

    We could at that point make a call to get_user_meta() (https://github.com/verygoodplugins/wp-fusion-lite/blob/master/includes/class-user.php#L441) to get all the data that’s in the database for the user. That would ensure that everything has passed through any relevant filters already.

    But:

    a.) We don’t know that every plugin has saved everything at that point
    b.) The idea was to only sync the data to the CRM that has *just* been updated. For performance and simplicity reasons. If you have 100 fields enabled for sync we wouldn’t want to send all of them just because someone updated their billing address.

    So then I thought about array_intersect-ing the $_POST data with the data from the database to get the filtered values from the DB *only* for the fields that were POST’ed.

    But the field keys also sometimes change between the POST data and the database. For example on user-edit.php in the admin, the input is “url”, but it’s saved to the DB as “user_url”.

    So *then* I thought, instead of using the user_update action, we could use the insert_user_meta filter to get only the values that were being changed. But it felt weird to me to attach functional code to a filter… an action is more appropriate.

    Any thoughts?

    Also do note we have our own filter that lets you modify just data going to the CRM, in case it helps: https://wpfusion.com/documentation/filters/wpf_user_update/

    Jack

    Hey @verygoodplugins / Jack,

    Thanks for the continued thoughts on this. Perhaps the simplest solution for this use case is to hook into the wpf_user_update and wpf_user_register filters as you suggest. This does require duplicating the code but its only a few simple lines. I’ve tested and deployed this and all appears to be working as expected. If you do decide to make any more complex architectural changes do let me know but for now we’re at least getting cleaner data into the CRM 🙂

    
    // WP Fusion Sync - Raw Form Data is Synced so Format (again)
    function wpf_format_user($user_meta, $user_id) {
    	if( isset( $user_meta['first_name'] ) ) {
    		$user_meta['first_name'] = (ctype_upper(str_replace(' ', '', $user_meta['first_name'])) ? ucwords(strtolower($user_meta['first_name'])) : ucwords($user_meta['first_name'])); 
    	}
    	if( isset( $user_meta['last_name'] ) ) {
    		$user_meta['last_name'] = (ctype_upper(str_replace(' ', '', $user_meta['last_name'])) ? ucwords(strtolower($user_meta['last_name'])) : ucwords($user_meta['last_name']));
    	}
    	if( isset( $user_meta['email'] ) ) {
    		$user_meta['email'] = strtolower(sanitize_email($user_meta['email']));
    	}
    	return $user_meta;
    }
    add_filter('wpf_user_update', 'wpf_format_user', 10, 2);
    add_filter('wpf_user_register', 'wpf_format_user', 10, 2);
    
Viewing 4 replies - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.