Get Multi-Options Interests and add a new Interest

I am using the PHP wrapper and need to first get a members existing Interests, then append any new Interests they may have selected. Otherwise, my add will lose all existing Interests. I couldn't find a good sample of this using PHP wrapper. Tried something like this:

$wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
$result = $wrap->get($email);

This returns an Object. Can I  cast this to an array and then look for my target 'Interests' Key, like this:

foreach($result->response->CustomFields AS $object) {

      $array = (array) $object;

      if ($array['Key']=='Interests') {

          $interestsArr[] = $array['Value'];

      }
  }

Then when re-subscribing, I'm not sure how to best integrate the Interest array back in to this:

$wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
      $result = $wrap->add(array(
          'EmailAddress' => $email,
          'Name' => $name,
              'CustomFields' => array(
                  array(
                      'Key' => 'Company',
                      'Value' => $company
                  ),
                  array(
                      'Key' => 'interests',
                      'Value' => $interests
                  )
              ),
              'Resubscribe' => true
          ));

I'm sure there must be a fairly straightforward way to do this.
Thanks for any snippet!

Marc

benz, 4 years ago

Assuming that your interests field is just a list of words in a text field can you just implode the array?

'Value' => implode(",", $interestsArr)

Annoyingly though the CONTAINS operator doesn't work when building segment rules against Custom Text fields - which makes storing data as a list kind of useless (I'd been wanting to do this as well) if you want to make use of it inside campaign monitor itself.

Alternatively if (as the post title suggests) it's actually a multi option field, the API does seem to support keeping existing options and appending new ones - at least according to http://www.campaignmonitor.com/api/lists/#updating_custom_field_options

drpudding, 4 years ago

Thanks, benz.

I've tried setting 'KeepExistingOptions' => true  both within the Custom Fields array, and the specific Interests array, but with no luck. Looking at the API, it sounds like the section you refer to is for adding/keeping the options that are available, not which options are selected. Though I may be reading it wrong.

Updates the available options for an existing Multi-Valued custom field

As far as your implode() suggestion, I did try that earlier but couldn't seem to get the syntax right for merging that string back into the PHP wrapper format, which appears to require a new array for each Interest, not a string. That is where I'm stuck.

Can't seem to get the syntax quite right, and would love to see a simple example fully coded.

Marc

benz, 4 years ago

Weird, it should work - have you set the debug level to verbose to see what it's doing?
One thing I found very, very, helpful was to modify the _call method in the base class to log the outgoing data structure.
In base_classes.php around line 220 I changed it to be this

    /**
     * Internal method to make a general API request based on the provided options
     * @param $call_options
     * @access private
     */
    function _call($call_options, $method, $route, $data = NULL) {
        $call_options['route'] = $route;
        $call_options['method'] = $method;
        
        if(!is_null($data)) {
            $call_options['data'] = $this->_serialiser->serialise($data);
        }
        
        $call_options = array_merge($this->_default_call_options, $call_options);
        $this->_log->log_message('Making '.$call_options['method'].' call to: '.$call_options['route'], get_class($this), CS_REST_LOG_WARNING);
 

        $this->_log->log_message('Call options: <pre>'.var_export($call_options, true).'</pre>',     //benz new line
            get_class($this), CS_REST_LOG_VERBOSE);        
            
        $call_result = $this->_transport->make_call($call_options);

        $this->_log->log_message('Call result: <pre>'.var_export($call_result, true).'</pre>',
            get_class($this), CS_REST_LOG_VERBOSE);

        if($call_options['deserialise']) {
            $call_result['response'] = $this->_serialiser->deserialise($call_result['response']);
        }
         
        return new CS_REST_Wrapper_Result($call_result['response'], $call_result['code']);
    }

Then in csrest_subscriber.php in the constructor I set the debug level to CS_REST_LOG_VERBOSE so it would echo everything out as it went. I picked up a few serialisation problems with the array structures that I was trying to send that way - it also made inspecting the response a lot easier.

Phil Phil, 4 years ago

Hi drpudding,

The documentation for adding subscribers describes how to handle multi-option select-many fields. I quote: "Multi-Valued Select Many custom fields are set by providing multiple Custom Field array items with the same key". The expected request body shows an example of exactly that.

In your case you would pass in multiple interests by directly porting the example json into equivalent php. First assign $interest_one and $interest_two and then:

$wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
      $result = $wrap->add(array(
          'EmailAddress' => $email,
          'Name' => $name,
              'CustomFields' => array(
                  array(
                      'Key' => 'Company',
                      'Value' => $company
                  ),
                  array(
                      'Key' => 'interests',
                      'Value' => $interest_one
                  ),
                  array(
                      'Key' => 'interests',
                      'Value' => $interest_two
                  )
              ),
              'Resubscribe' => true
          ));

It's probably also worth checking out the various options for clearing values provided by the update route, which is a better way to modify existing subscribers.

drpudding, 4 years ago

Phil,

Thanks for responding! I understand the format, but am unclear on how to format the existing interests array data I get from this get method:

$wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
$result = $wrap->get($email);

foreach($result->response->CustomFields AS $object) {

      $array = (array) $object;

      if ($array['Key']=='Interests') {

          // ??? HOW TO FORMAT THE DATA HERE...???

      }
  }

$wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
      $result = $wrap->add(array(
          'EmailAddress' => $email,
          'Name' => $name,
              'CustomFields' => array(
                  array(
                      'Key' => 'Company',
                      'Value' => $company
                  ),

                 // ??? TO GET IT TO WORK HERE ???

              ),
              'Resubscribe' => true
          ));

Also, for my purposes, is it ok to use the add method on an existing subscriber, as opposed to update?


Marc

drpudding, 4 years ago

Benz --
I think the issue is related to the expected format that Phil mentions above. The interests must be merged back as separate arrays. If I can solve formatting my get data that way, I can check the serialization debug.

Marc

drpudding, 4 years ago

Should anyone happen upon this, I have a working solution.

If using the PHP wrapper, to retain existing interests, while adding new ones, you need to first get back arrays of the existing interests, adding them to a custom fields  "container" array, then push in new arrays for the new interests and any other custom field arrays in your form. In the end, you have a multi-dimensional array one level deep, which gets entered for all Custom Fields combined.

Here is some sample code I have working:

           // ALL custom fields will get stored in this array
            $custom_fields = array();
           
            array_push($custom_fields, array('Key' => 'Company','Value' => $company));
            array_push($custom_fields, array('Key' => 'Role','Value' => $role));
            array_push($custom_fields, array('Key' => 'Interests','Value' => $interests)); // new interest
           
       $wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
        $resultGet = $wrap->get($email);

            // add in the existing Interests
            foreach($resultGet->response->CustomFields AS $object) {
           
                $array = (array) $object;
               
                // exclude the Value checked ($interests)
                if ($array['Key']=='Interests' AND $array['Value'] != $interests) {
                  array_push($custom_fields, $array);
                }
            }
           
            $wrap = new CS_REST_Subscribers(CM_LIST_ID, CM_API_KEY);
            $resultUpdate = $wrap->update($email, array(
                'EmailAddress' => $email,
                'Name' => $name,
                'CustomFields' => $custom_fields,
                'Resubscribe' => false
                ));


Thanks to all,

Marc

Join 200,000 companies around the world that use Campaign Monitor to run email marketing campaigns that deliver results for their business.

Get started for free
1-888-533-8098