CF7 Menus with Pipes

March 23rd, 2016

This comes form a user who is using pipe characters “|” in a menu field in a Contact Form 7 form. Here is an example Contact Form 7 form field definition:

What does this do? Only the information before the “|” character display to the user in the form:

But the value that is sent in email and saved to the database is the value after the “|”. In this example, if a person selects “location1” what is actually submitted is “email1@nowhere.com”.

This is very useful if you want your form submissions emailed to a different email address depending on what a user selects. For example, if the user selects “location1” you might want the form email sent to “email1@nowhere.com”. Similarly, “location2” gets emailed to “email2@nowhere.com” and “location3” to “email3@nowherel.com”.

To achieve this, in the Contact Form 7 edit page, simply put the “location” field tag in the mail’s “to” field.

And in the form Email section:
To field

Remember: for the [location] field, the user may choose “location1” (what is before the “|”) but the value that CF7 reports is “email1@nowwhere.com” (what is after the “|”).

So far, so good. But in the database, what is saved for the location field is the email address (what is after the “|”). But what if you want to save the other part or both? As it stands, we get data like:

But what we might prefer is this:

To achieve this, we must create a filter using the Shortcodes, Actions and Filters plugin. Create a new code item with the following code.

(Updated code. Earlier version of code here no longer worked with the latest CF7)

Note: Do not repeat any email addresses in the choices, otherwise it is not guaranteed to give you the correct associated location value. Please see this thread.

Add this function. If using Shortcodes, Actions and Filters, I recommend that you add this as its own Action code element. Add this one first. Be sure to activate it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function form_with_pipes_handler($formName, $fieldName, $newFieldName, &$formData)
{
    if ($formData &&
            $formName == $formData->title &&
            property_exists($formData, 'WPCF7_ContactForm') &&
            method_exists($formData->WPCF7_ContactForm, 'form_scan_shortcode')) {
 
        $scanned_form_tags = $formData->WPCF7_ContactForm->form_scan_shortcode();
        $emailSelected = $formData->posted_data[$fieldName];
        if (is_array($emailSelected) && count($emailSelected) == 1) {
            $emailSelected = $emailSelected[0];
        }
        $valueSelected = null;
        foreach ($scanned_form_tags as $tag) {
            if ($tag['name'] == $fieldName) {
                foreach ($tag['raw_values'] as $rawValue) {
                    // value|email
                    $valuesArray = explode('|', $rawValue);
                    if (count($valuesArray) == 2 && $valuesArray[1] == $emailSelected) {
                        $valueSelected = $valuesArray[0];
                        break;
                    }
                }
            }
            if ($valueSelected != null) {
                break;
            }
        }
        if ($valueSelected != null) {
            $formData->posted_data[$fieldName] = $valueSelected;
            $formData->posted_data[$newFieldName] = $emailSelected;
        }
    }
    return $formData;
}

The above is a re-usable function that is only added once. The following is a code function to deal with your specific form. You can add multiple versions of the following code. Add one for each form. In Shortcodes, Actions and Filters, make each one its own code element so that you can activate/deactivate each independently. But you must be sure to have different function name for each.

Make the following changes in the code below

In the code, change the values for $formName and $fieldName to match your form and field.

1
2
3
4
5
6
7
8
function location_form_handler($formData) // Use a different function name for each form
{
    $formName = 'Pipes'; // change this to your form's name
    $fieldName = 'location'; // change this to your field's name
    $newFieldName = $fieldName . '_email';
    return form_with_pipes_handler($formName, $fieldName, $newFieldName, $formData);
}
add_filter('cfdb_form_data', 'location_form_handler'); // ensure 2nd param matches above function name

This code makes sure that the “location” field now always has the value before the “|” (like “location1”) and never the value from after (like “email1”). At line 36, the code artificially injects a new field named “location_email” to hold what is after the “|”. At line 35 it re-assigns the value of the location field (which was the email value) to the display value (what was before the “|”).

GMail trick for testing multiple emails
Let’s say you have a GMail email: “somebody@gmail.com”. You can send email to this address but with extra information in it using “+”. Examples:

  • somebody+location1@gmail.com
  • somebody+location2@gmail.com
  • somebody+location3@gmail.com

Messages sent to any of these emails will all go to the somebody@gmail.com account. Effectively everything from the “+” to the “@” is ignored for purposes of delivering the email. But you will see this extra information in the “To” field of the email you receive.

This is useful to testing when you want to use different email addresses but you want them to come to the same account. In GMail you can also set up filters on the “To” field to treat these messages differently from each other.

This may work with other email providers, but I haven’t tried it.

FYI: example structure of $scanned_form_tags

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Array
(
    [0] => Array
        (
            [type] => select
            [basetype] => select
            [name] => location
            [options] => Array
                (
                )
 
            [raw_values] => Array
                (
                    [0] => location1|email1@nowhere.com
                    [1] => location2|email2@nowhere.com
                    [2] => location3|email3@nowhere.com
                )
 
            [values] => Array
                (
                    [0] => location1
                    [1] => location2
                    [2] => location3
                )
 
            [pipes] => WPCF7_Pipes Object
                (
                    [pipes:WPCF7_Pipes:private] => Array
                        (
                            [0] => WPCF7_Pipe Object
                                (
                                    [before] => location1
                                    [after] => email1@nowhere.com
                                )
 
                            [1] => WPCF7_Pipe Object
                                (
                                    [before] => location2
                                    [after] => email2@nowhere.com
                                )
 
                            [2] => WPCF7_Pipe Object
                                (
                                    [before] => location3
                                    [after] => email3@nowhere.com
                                )
 
                        )
 
                )
 
            [labels] => Array
                (
                    [0] => location1
                    [1] => location2
                    [2] => location3
                )
 
            [attr] => 
            [content] => 
        )
 
    [1] => Array
        (
            [type] => submit
            [basetype] => submit
            [name] => 
            [options] => Array
                (
                )
 
            [raw_values] => Array
                (
                    [0] => Send
                )
 
            [values] => Array
                (
                    [0] => Send
                )
 
            [pipes] => WPCF7_Pipes Object
                (
                    [pipes:WPCF7_Pipes:private] => Array
                        (
                            [0] => WPCF7_Pipe Object
                                (
                                    [before] => Send
                                    [after] => Send
                                )
 
                        )
 
                )
 
            [labels] => Array
                (
                    [0] => Send
                )
 
            [attr] => 
            [content] => 
        )
 
)
  1. Michael Simpson
    January 29th, 2013 at 16:34 | #1

    A comment from a user:

    In my form, visitors who fill out the form select the state they are located in, then the salesperson who is responsible for that state receives the email. As well, I needed the email to be sent to a central (corporate) email address.

    However, not all states have an assigned salesperson, being the company focuses on the mid-west.

    With Contact Form 7, if the email address after the pipe was empty, emails would not be sent. The method outlined by Michael actually allows an empty field after the pipe.

    I set up “Mail” in the form to send to the central email and “Mail (2)” to send to the salesperson (if one exists).

  2. wala
    February 5th, 2013 at 04:15 | #2

    hey ,
    Thank you for this helpful post .
    I want ask you ask you about somethings , I want store ID from textbox in database , Can I check first If this id exists in db or not ? and show message to user

    • Michael Simpson
      February 5th, 2013 at 10:32 | #3

      To do that, you need to hook into CF7 when it validates data. This post describes a hook called after validation is done and the post is submitted. Have a look at this post.

  3. wala
    February 6th, 2013 at 05:09 | #4

    Thank you very much : )

  4. Dee
    August 5th, 2013 at 11:08 | #5

    I have followed the steps listed in your article to send mails to separate IDs depending on the selection. However I get the red box wrror message: Failed to send your message. Please try later or contact the administrator by another method.
    Any suggestions on how i can solve this problem?
    Thank you!

    • Michael Simpson
      August 5th, 2013 at 14:04 | #6

      This indicates there is some error happening in your PHP code. You will need to figure out what that is and fix it.

Comments are closed.  Go To Support Forum