Code Description

After submission we save a rates CPT with some info including the transaction ID. (functions.php save_entry_data_to_rate_results()

In the Turborater plugin

On gform_confirmation we add the spinner and fire off the rater_ajax call in js, passing entry ID and transaction ID (rater_ajax()).

On frontend we call back to PHP and the rater_request function. This generates a payload that we can send off to Turborater to begin quoting. Part of the payload is an API call figuring out which companies to rate with. This is determined mainly by STATE and Line of business. If we have a carrier setup in Turborater’s admin for a STATE & LOB that matches the user request then it gets returned to us to rate and goes into the ‘CarrierInformation’ in the payload.

We create a transaction ID on our end and then prepend either HO or PA for Homeowner or Personal Auto rating. So a transaction id of 100 in our system will correspond with a turborater transaction id of either PA-100, HO-100 or both.

If the user is rating both home and auto these are two separate requests and responses. In the initial ajax call we set a value on the page in a hidden input id ‘lltr’ (lines left to rate). If we’re rating both, then this is set to 2 otherwise just 1. On the frontend we update the value whenever a rate check comes back ‘RatingComplete’ till we reach lltr: zero. Then we redirect to results.

When Turborater responds ‘Success’ (literally) this means it has accepted the payload without errors. Now it’s doing its thing rating with various carriers, which could take some time. We wait 8 seconds and then call js get_rates to start polling for the rate results.

Get_rates call rater_retrieve_rates on the backend. It keeps checking the response and waiting for either the value ‘RatingComplete’ to be true for all lines of business being rated (home & auto), or to have looped 8 times. You can change this count if you want to wait longer.

If RatingComplete happens, then Turborater is done working and we grab the results, parse them and save them to the rates CPT in the DB. Before saving them we do a few things to process:

  1. We add an ‘AdjustedRate’ value which calculates discounts for our top carriers. This helps us recommend some rates over others even if their price is lower. So an A+ carrier that returns a rate of $1000 will get 20% taken off that and we will display results as if the price were $800. We will still obviously show the $1000 to the user, but the $800 is our adjustedRate to sort by on the frontend.

We save them as an array of objects in a meta field.

If we’ve looped 8 times and still aren’t done, then we’re basically giving up. We save what we have (maybe some are done) and on the frontend redirect to the results page /rates, passing the transactionID as a parameter ‘?t=’.

Salesforce Lead

Happens in theme/inc/salesforce-functions.php and theme javascript

On submission we submit an ajax request to create a lead with Rating: Cold. We use Ajax so we don’t have to wait on PHP to start turborating – otherwise it blocks.

This happens on the gform_confirmation hook in ajax_salesforce function in the theme.

This triggers the ajax function which in turn comes back to PHP to make the API call from salesforce_create_lead.

The returned SF ID is saved to the Rate CPT in salesforce_save_lead_id function allowing us to later update the lead with rate results.

When allrating is complete we hit rater_save_results in the turborater plugin, which also calls update_sf_lead. This triggers an update to the existing SF Lead, adding our returned rates to the Lead Description field in SF.

And finally if the user clicks ‘Select rate’ then we take them to a template-part ‘content-selected-rate’ in the theme that again hits ‘update_sf_lead’ via ajax with the selected rate and the updated rating ‘Hot’.

The user can potentially go back and select a different rate. We will only ever show the most recent one they selected.

Rate Results

In the /rates page we have a custom template page-rates.php that grabs the param, finds the CPT, parses out the results value and shows the results.

It also handles if we don’t have a transaction ID and fails gracefully.

To display in the correct order we use a function called ‘sort_results’. It has a usort function to sort the array by the adjustedRate. And then it moves any $0 values to the end.

If a user selects a rate it takes them to a page showing only that rate and updates SF with the new info (rating:hot and selected lead name).

Test Submission

If you want to test and don’t want to fill in all the fields, you can submit again using a previously submitted entry ID.

Just be sure to remove the corresponding Rate CPT post since it will generate a duplicate otherwise and be tricky to troubleshoot.

To test with an existing EntryID change the entryID in these files:

  • Theme functions.php save_entry_data_to_rate_results, set the $entry to an ID.
  • prosper-turborater-public.php change ajax_rater with the same $entry line.

This basically just overrides GF’s entry object from the /test form to use the entry you submit.

And if you want to also test the SF integration, change to the same ID in theme/inc/salesforce-functions.php


If the user is rating both home and auto we will display potential bundles as recommended. Usually there are discounts and benefits to bundling the two with the same company. We only consider home/auto from the same company a true bundle, even though this isn’t entirely accurate (some carriers let us get the bundle discount with other carriers).

When the user lands on the result page we try to create a $bundles array of objects in content-results.php. This calles tr_create_bundles in util-functions which first checks if we have both home and auto results, and otherwise returns false.

We then build bundle objects per carrier that have a carriername, the auto premium, home premium and bundlepremium. We get the bundle premium by simply combining the two premiums. If there is a bundle discount from the carrier we already have the bundle rate because in our rate request we told the carriers that we’re also buying the other LOB with this carrier. So we don’t know what the rate would be if they did not bundle. That would require making an additional rate request per LOB and saving this as a non-bundle rate. We don’t do this – we just show them the lowest rate they could get, which is the bundle.

If we succesfully build a bundle array of bundle objects then we save it to the quote as bundleResults so we can access this info on the content-selected-rate page without rebuilding the array a 2nd time.

We also make sure to change the unsetting if our small result cards, which otherwise would exclude the #1 rate to avoid showing redundant results.

If a carrier has both a home and auto rate we can assume that the rate is only good as part of a bundle. So we check if the carrier name is in the bundle array and show the disclaimer ‘Note: This rate requires bundling’.