Detecting and Syncing Additional Fields

#Overview

If you’re reading this page then you’re probably trying to sync a field value with your CRM that isn’t currently supported by WP Fusion.

While WP Fusion can sync any data from WordPress to contact records in your CRM, it does not work “auto-magically” with every piece of data you see in your WordPress admin. That has to do with where your field data is stored.

We can break the kinds of data that WP Fusion syncs into three categories:

  1. Data from the normal user tables – Works great with no extra setup
  2. User data that’s in a different table – Requires some work
  3. Data that’s calculated or not related to a specific user – Can be difficult

#Normal tables

WP Fusion can automatically detect and sync any data found in the wp_users and wp_usermeta database tables bidirectionally with any fields in your CRM.

Syncing data between just two tables (your users and your CRM) is automatic and requires no extra setup

These tables are the standard place where most plugins store data relating to a specific user. So even if WP Fusion doesn’t have a specific integration with a plugin, it’s likely the fields from that plugin will still show up under the Additional Fields section in the Contact Fields settings, and can be synced with your CRM without any extra work.

Note: To build the list of Additional Fields, for performance reasons WP Fusion only scans the usermeta of your own admin user. If you’ve just added a new field and it’s not showing, try saving some data in that field for your own admin user.

#User data that’s in a different table

Some plugins, like BuddyPress, store user profile data in different database tables.

When we talk about WP Fusion having an “integration” with a membership plugin (like the ones listed here), that means WP Fusion has additional code to:

  • Detect the available fields from that plugin’s custom tables, and list them in the Contact Fields in the settings
  • Extract the data from the custom tables and sync it to your CRM
  • Detect when data has been loaded from your CRM, and if that data belongs in a custom table, store it there

For example with BuddyPress, let’s say we have a custom XProfile field for Favorite Color, in the wp_bp_xprofile_data table. How that sync looks visually is something like:

Syncing data between your CRM and multiple WordPress tables can require some extra attention if using a non-supported plugin

And then in the code, that requires three functions:

#Detect the custom fields and list them for sync

Step one is figuring out which fields are available, and using the wpf_meta_fields filter to register them as available for sync.

With BuddyPress we make use of the bp_xprofile_get_groups() function, like

function example_prepare_buddypress_fields( $meta_fields ) {

	// Get the field groups

	$groups = bp_xprofile_get_groups( array(
		'fetch_fields' => true,
	) );

	foreach ( $groups as $group ) {

		foreach ( $group->fields as $field ) {

			// Register the field in the list using the ID and label

			$key = 'bbp_field_' . $field->id;

			$meta_fields[ $key ] = array(
				'label' => $field->name,
				'type'  => $field->type,
			);

		}
	}

	return $meta_fields;

}

add_filter( 'wpf_meta_fields', 'example_prepare_buddypress_fields' );

Which makes the fields show up for sync in the settings like this:

#Extract the data from the custom table and sync it to the CRM

When a user registers or a Push User Meta operation is run, WP Fusion tries to get all of the data it can out of the database for that user.

That data is then passed through the wpf_get_user_meta filter, which allows us to merge in data from different sources.

For example the code to load and sync the XProfile data would look like:

function example_get_buddypress_fields( $user_meta, $user_id ) {

	$profile_data = BP_XProfile_ProfileData::get_all_for_user( $user_id );

	// Get the profile data and merge it into the user_meta

	foreach ( $profile_data as $field ) {
		$key               = 'bbp_field_' . $field['field_id'];
		$user_meta[ $key ] = $field['field_data'];
	}

	return $user_meta;

}

add_filter( 'wpf_get_user_meta', 'example_get_buddypress_fields', 10, 2 );

#Load data from the CRM into the custom tables

Then, going the other direction, we want to make sure that data loaded from the CRM is properly stored in the custom database table, not the wp_usermeta table.

For that we make use of the wpf_set_user_meta filter. For example with BuddyPress, that code looks like:

function example_set_buddypress_fields( $user_meta, $user_id ) {

	foreach ( $user_meta as $key => $value ) {

		if ( strpos( $key, 'bbp_field_' ) === 0 ) { // If the field key starts with bbp_field_

			$field_id = str_replace( 'bbp_field_', '', $key );

			$field        = new BP_XProfile_ProfileData( $field_id, $user_id );
			$field->value = $value;
			$field->save(); // Save the field to the wp_bp_xprofile_data table

			unset( $user_meta[ $key ] ); // unset() the value so it's not saved to wp_usermeta

		}
	}

	return $user_meta;

}

add_filter( 'wpf_set_user_meta', 'example_set_buddypress_fields', 10, 2 );

And there you have it. With those three code snippets, you can register and bidirectionally sync a user meta field from a custom database table.

#Data that’s not in a table

There may be some things you’d like to sync with your CRM that aren’t actually stored in any one place. Some examples:

  • Customer lifetime value
  • Most recently commented post
  • Most recent quiz score
  • Subscription renewal date

With things like this, they aren’t actually stored in any one place in the database that can be directly synced with your CRM, you’d have to write the code to calculate the values.

#Register the field

For example, let’s say you want to sync a WooCommerce customer’s lifetime value with your CRM. First register the field in the WP Fusion settings.

function example_prepare_ltv_field( $meta_fields ) {

	$meta_fields['lifetime_value'] = array(
		'label'  => 'Lifetime Value',
		'group'  => 'woocommerce',
		'pseudo' => true,
	);

	return $meta_fields;

}

add_filter( 'wpf_meta_fields', 'example_prepare_ltv_field' );

In this example we’ve set pseudo to true to indicate that the field doesn’t really exist. This is optional but it stops WP Fusion from loading the value back from your CRM, and filling up your database with unnecessary meta values.

#Calculate and sync the data

Similar to the BuddyPress example, we’ll use the wpf_get_user_meta filter to merge the custom value into the data that’s being sent to the CRM.

function example_sync_lifetime_value( $user_meta, $user_id ) {

	$user_meta['lifetime_value'] = 0;

	$customer_orders = get_posts( array(
		'posts_per_page' => -1,
		'post_type'      => 'shop_order',
		'post_status'    => wc_get_is_paid_statuses(),
		'meta_key'       => '_billing_email',
		'meta_value'     => $user_meta['billing_email'],
		'orderby'        => 'ID',
		'order'          => 'DESC',
	));

	if ( ! empty( $customer_orders ) ) {

		foreach ( $customer_orders as $order_id ) {

			$order = wc_get_order( $order_id );

			$order_total = $order->get_total();

			$user_meta['lifetime_value'] += floatval( $order_total );

		}
	}

	return $user_meta;

}

add_filter( 'wpf_get_user_meta', 'example_sync_lifetime_value', 10, 2 );

In this case, the code is quite a bit more complicated, since we’re not just pulling the data out from another part of the database. To calculate the lifetime value you first need to search for all orders placed by that customer, and then for each order increment the lifetime value field by that order’s total.

This also can introduce performance problems on stores with a large number of orders. In those cases you might want to cache the value using a transient, or create a separate meta key that tracks the customer’s LTV and is incremented with each new order.

#Examples

#Sync booking dates from multiple FooEvents products to different date fields in the CRM

#Sync subscription fields from multiple subscription products to their own fields

This example works with WooCommerce subscriptions, it registers each of your subscription products as a separate field on the contact fields list. For each you can sync the renewal date, status, and start date to a separate custom field in your CRM.

Was this helpful?