The problem you’re running into is that the $customer_appointment_id you’re trying to use in your before_email function is kind of like a stranger to that function. They haven’t met before, so before_email doesn’t recognize $customer_appointment_id when you’re trying to use it.
So how do you introduce them? Well, one way is by using a ‘global’ variable. It’s like making your secret public. After you insert a record and set the insert id, you can do this:
global $customer_appointment_id;
$customer_appointment_id = $wpdb->insert_id;
What this does is it shouts out $customer_appointment_id to the whole script, and then anyone (any function) who wants to use it can.
Then in your before_email function, you can bring it in like this:
add_filter('gform_pre_send_email', 'before_email');
function before_email($email) {
global $customer_appointment_id;
$email['message'] = str_replace('appt_id=0', 'appt_id='.$customer_appointment_id, $email['message']);
return $email;
}
Here you’re saying, “Hey function, remember that $customer_appointment_id we made public? We’re going to use it here.”