How To Encrypt (and Decrypt) Fields With Formidable Forms


One of the common concerns I kept bumping up against was how to collect sensitive information from clients securely. For me, more often than not, it was for one of two main reasons. One was getting credit card information (if they weren't comfortable providing that info over the phone). The other was when taking on new Care Plan clients whose site I hadn't built (requiring me to request things like host and site login credentials for an audit).

In both of those cases, I don't want the client to email such details to me, simply because there are so many points on that email's journey where that data could be compromised - especially because everything is in plain clear text. So that was a big no-no.

In the past, I have used services like NoteShred which allowed me to pass on sensitive information knowing it gets auto destroyed after being read once. The issue for me there is, whilst the "note" is password-protected, communicating that password (to allow the recipient to open the note) requires being communicated to them in some other way (email, chat, text, phone etc). Overall, whilst a lot more secure than just email, it still made me a little uncomfortable.

Most agencies like mine face this challenge. Yes, I know there are numerous paid-for services/plugins that can address this. However, for me, I couldn't shake off knowing that there must be a better way of doing this using my own WordPress site to handle this.

Now, I use Formidable Forms (FF) as my form builder of choice, and forms built with this are the main way I get any information (sensitive or otherwise) from visitors and clients. So surely I could create forms for those two use cases?

The answer is of course - easily. The challenge is that FF saves the collected information to the WordPress database in plain text (as do all form builders, I believe). Sure, this is more secure than sending sensitive data around in emails. However, if my site should get hacked/compromised then all that golden information is easily readable. So that's not good.

So I went on a Google hunt; surely someone else must have done this. It took quite a while (lots of blind alleys and rabbit holes) but I stumbled on a great post by Victor Font addressing this very issue. All the key points I needed were there (so, a very big thank you, Victor, for writing that post).

This post here is very much built on the foundations of that post. So why write another post on this? Well, whilst Victor's post pointed me in all the right places, it still took me a while to implement it and get it all working. So I wanted to go a little further and fill in some of the blanks I had to figure out for myself. If you want to check out Victor's post you can find it here.

So, the purpose of this post is to show you everything you need to do so you can collect that sensitive information through a form, and then encrypt it before writing it to the WordPress database (and, of course, decrypt it after). So if you did, unfortunately, get hacked - at least your clients' sensitive data is not compromised.

Whilst this post specifically focuses on Formidable Forms, the theory and principals should also work for the other big form builders out there like Gravity Forms, NinjaForms etc. Naturally, any equivalent hooks will differ and the suggested code would need to be re-jigged.

I don't believe (at the time of writing) that any of these form builders offer the ability to encrypt field data natively. That said, and not sure how true this is, but I gather this is on FF's roadmap at some future time (no idea when), but until then...

A Few Caveats

Before we get started:

  1. I mentioned earlier using these methods to possibly collect credit card details. You absolutely can, but it is recommended you don't (unless you want to go through all the hoops to be PCI compliant and/or understand the risks of holding customer/client credit card details). I use payment gateways wherever possible because they are PCI compliant and all the risk is with them.
  2. This really isn’t that hard to do, but you do need to be comfortable editing WordPress config files like functions.php and wp-config.php. If not, then stop and get someone who is to follow this.
  3. This is offered as-is with no support, implied or otherwise. That said, I will endeavour to respond to any comments/questions in the comments section, time permitting.
  4. If you follow this and it messes up your site I take no responsibility. That said if you take the usual precautions before starting this, like making sure your site and database is FULLY backed up. If you do run into problems you can restore your site back to its former glory. Or better yet try it out on a staging/cloned site.


In order for this to be set up and working, there are few dependencies that need to be in place:

Getting Started

The first thing we need to do is make a change to wp-config.php.

Before that, a couple of points regarding wp-config.php. Usually, by default, this key file is in the root folder of your site. The downside to this is if your site is hacked, then any information in there is compromised, such as database user name and password, plus other stuff like that. To mitigate this you should consider moving that file up a level so it's not in the root folder of your site (i.e. it's no longer a publicly accessible file). This means someone would have to hack your host to get to that file. Whilst not impossible, it's a much harder proposition for a hacker. I use Gridpane to host many of my sites, and by default, they already have it set that wp-config.php is outside the site's root folder.

Now, you cannot simply move the file; WordPress needs to know where it resides. Remember, you don't have to do this, but if you wish to, this article describes how to do just that. If you do move it, remember to update any backup plugin so it knows where that file is now.

Wherever your wp-config.php file resides, the first thing is to define some constants in there. Calls to OpenSSL, later on, will use these. The following sample lines should be added somewhere in your wp-config.php file.

define('FORMIDABLE_SALT', 'bzD?Vi&+s!i{PjUCN2N_+gUQ:`|wt::O/+~!es[pRi%-<JPS<8*Eu1%}R(nmdqY2'); define('FORMIDABLE_METHOD', 'AES-256-CBC'); define('FORMIDABLE_OPTIONS', 0); define('FORMIDABLE_IV', '!MJekYW9G^6juRBH');
Code language: PHP (php)

These lines basically define 4 "constants". The last one, for example, defines a constant with the name of FORMIDABLE_IV to have a value of "!MJekYW9G^6juRBH". Essentially, this definition acts like a global variable, except the value cannot be changed, hence why it is known as a "constant". This will save us having to state these values in multiple places. We define them in wp-config.php once, and then reference those constants whenever they're required in OpenSSL function calls.

NOTE: You will need to replace the values for FORMIDABLE_SALT and FORMIDABLE_IV with your own values. This is quite easy to do - and I'll show you how shortly, but first, let's just look at OpenSSL and what these constants are actually going to be used for.


As mentioned earlier we will be using OpenSSL to do the actual encryption/decryption. This is done by calling the openssl_encrypt() and openssl_decrypt() functions respectively.

A call to either looks like:

openssl_encrypt( $data, $method, $key, $options, $iv ); // to ENCRYPT something openssl_decrypt( $data, $method, $key, $options, $iv ); // to DECRYPT something
Code language: PHP (php)

As you can see, both calls require the same parameters. When we call these functions later on, we will be using our constants for these parameters (except for $data). So what do they mean?

As mentioned earlier, the list of 4 constant defines earlier is just an example. Lines 2 and 3 are fine as is, however you will need to replace the values for FORMIDABLE_SALT and FORMIDABLE_IV with your own values.

For FORMIDABLE_SALT, the easiest way is to visit and copy any one of the generated result values.

For FORMIDABLE_IV, use your favourite password generator to generate a 16-character string.

Once your constants have been added to your wp-config.php file ensure you make a secure copy of those details somewhere else where you'll never lose them. They are required for both encrypting and decrypting. If you lose them you will NOT be able to decrypt any data that was encrypted that used those keys. You have been warned!

The Functions

The final piece of the puzzle is made up of 5 small functions. These should all be added to your functions.php file (preferably within a child theme).

General Encrypt/Decrypt Functions

The first 2 functions are the basic encrypt/decrypt functions. These will be called by the main functions (further down) as required to do the actual encrypting or decrypting, and as you can see they make use of the constants we defined earlier. Essentially, the first takes in data and returns an encrypted version of that data. The second takes in encrypted data and returns a decrypted version of that text.

/* Functions allowing Formidable functions to encrypt/decrypt field data in the database * - constants/salts are set in wp-config.php */ function adz_encrypt( $data ) { $key = FORMIDABLE_SALT; $method = FORMIDABLE_METHOD; $options = FORMIDABLE_OPTIONS; $iv = FORMIDABLE_IV; return openssl_encrypt( $data, $method, $key, $options, $iv ); } function adz_decrypt( $encrypted ) { $key = FORMIDABLE_SALT; $method = FORMIDABLE_METHOD; $options = FORMIDABLE_OPTIONS; $iv = FORMIDABLE_IV; return openssl_decrypt( $encrypted, $method, $key, $options, $iv ); }
Code language: PHP (php)

Formidable Forms ENCRYPT Function

With the constants defined and the basic encrypt/decrypt functions in place, how do we integrate that with a Formidable Forms form?

Below is an example Formidable Form highlighting the fields I specifically want encrypted (probably overkill, but hey).

example secure form

As you know, each form you have built with Formidable Forms has an ID, and each field on that form has its own ID too. You will need to know these and note them down.

Using the form above as an example, let's say the form's ID is 22, and the field IDs I want to be encrypted are 300 to 306 inclusive. The function would look like this:

// Encrypts specific fields on forms 22 and 30 add_filter('frm_pre_create_entry', 'adz_encrypt_my_field'); add_filter('frm_pre_update_entry', 'adz_encrypt_my_field'); function adz_encrypt_my_field($values) { if ( $values['form_id'] == 22 ) { // change num to your form id $values['item_meta'][300] = adz_encrypt( $values['item_meta'][300] ); // field $values['item_meta'][301] = adz_encrypt( $values['item_meta'][301] ); // field $values['item_meta'][302] = adz_encrypt( $values['item_meta'][302] ); // ... $values['item_meta'][303] = adz_encrypt( $values['item_meta'][303] ); $values['item_meta'][304] = adz_encrypt( $values['item_meta'][304] ); $values['item_meta'][305] = adz_encrypt( $values['item_meta'][305] ); $values['item_meta'][306] = adz_encrypt( $values['item_meta'][306] ); } if ( $values['form_id'] == 30 ) { // change num to your form id $values['item_meta'][400] = adz_encrypt( $values['item_meta'][400] ); $values['item_meta'][401] = adz_encrypt( $values['item_meta'][401] ); } return $values; }
Code language: PHP (php)

You'll also see a second "if" block for a second fictional form (ID 30) to illustrate how to manage multiple forms (that one just supposes 2 fields need encrypting). Just delete or comment out that entire "if" block if not required.

So what's it actually doing? Well, in order to encrypt form data, we need to intercept the data from the form after it has been submitted, but before the resultant entry is written to the database. To do this we can use two Formidable Forms hooks (frm_pre_create_entry and frm_pre_update_entry).

These are both called after a form is submitted and an entry is to be either created or updated - but they're called before any data is written to the database. This allows us to then take that data, encrypt it, and then pass it back to Formidable Forms to then be written to the database.

Formidable Forms DECRYPT Function - Backend

That's the encryption of fields sorted out. Now to decrypt them.

For this, you only need to know the field IDs. As these are all unique, the form ID is not required. In which case you can just list all the fields, regardless of what form they are associated with.

// Click "Edit" on Card Details or Audit Details form entry to see decrypted values // (NOTE: just "viewing" an entry won't decrypt it - entry needs to be "edited"), // Only field IDs needed, not form IDs add_filter('frm_setup_edit_fields_vars', 'adz_decrypt_my_field', 20, 3); function adz_decrypt_my_field($values, $field, $args) { if ( $field->id == 300 or // field $field->id == 301 or // field $field->id == 302 or // ... $field->id == 303 or $field->id == 304 or $field->id == 305 or $field->id == 306 or $field->id == 400 or $field->id == 401 ) { $values['value'] = adz_decrypt( $values['value'] ); } return $values; }
Code language: PHP (php)

This function decrypts the fields listed as and when an entry is EDITED (i.e. decryption does not occur if simply viewed). It does this by using the frm_setup_edit_fields_vars hook to intercept an EDIT of any of the listed fields from the database. When that happens it decrypts the passed value before passing the new decrypted value on to be displayed.

You can (if you wish) set permissions in the Formidable plugin for who can EDIT entries. This is useful if you only want to give that functionality to specific users - meaning those that don't have that permission will just see the "view" version of the entry, which will be the hashed gibberish.

Formidable Forms DECRYPT Function - Frontend "View" / Email etc

What if you need to decrypt fields, but not through the backend? For example, if you have a front-end Formidable Forms View designed for logged in users, say. Or perhaps to decrypt fields for an email (the latter is not recommended, but again, hey).

This uses frmpro_fields_replace_shortcodes hook which intercepts the data, and if a field's shortcode has the appropriate "decrypt" flag set it will then decrypt that field's before displaying the decrypted information.

// For views or other places that can use Formidable shortcodes, e.g. emailing out an entry etc. // Just need to add "decrypt=1" to the shortcode add_filter('frmpro_fields_replace_shortcodes', 'decrypt_my_field_for_view', 10, 4); function decrypt_my_field_for_view($replace_with, $tag, $atts, $field){ if(isset($atts['decrypt'])){ $encrypted = $replace_with; $replace_with = adz_decrypt($encrypted); } return $replace_with; }
Code language: PHP (php)

This will work for wherever you can put a Formidable shortcode. You just need to add “decrypt=1” as a parameter of the shortcode. For example, in a view, to show the decrypted values of 2 fields you’d specify:

<tr> <td>[177]</td> <!-- This field doesn't require decryption --> <td>[178 decrypt=1]</td> <!-- This field does --> <td>[181 decrypt=1]</td> <!-- This field does --> </tr>
Code language: HTML, XML (xml)

Armed with the constants and all of those functions you should now be good to go.

A Warning About Password Fields

One of the rabbit holes I ran down was with password type fields. And given, more often than not, it will likely be passwords you want to encrypt, you'll need to bear this in mind.

A Formidable Forms password field is like most password fields; it hides/masks the text that is typed into it. Fair enough, right? The issue comes when you need to see the decrypted password when editing the resultant entry that has such a field.

When you edit such an entry containing a password field, that field (even after being decrypted) still shows in the backend as masked so you can't read it! This stumped me for a little while. In that scenario, the only way to see the password was to use a tool like phpMyAdmin to find it in the metadata tables in the database, and then hack around decrypting it manually. Well, that sucked; and I certainly didn't want to have to do that every time.

Now, there may be a better way than this, but what I ended up doing to work around that was this.

For every password field in a form, I also created a "paired" hidden text field (usually with a label matching the password field's but with the word "(copy)" at the end) and then set that hidden field's Default Value to equal the field ID of the password field - see below for an example.

using hidden password text field

Then just ensure you include both fields in all the functions, and then the hidden field's decrypted value will be properly visible/available to you.


This was a lifesaver for me, and I hope this helps you out too. If you have any comments/questions, please do comment below.


With the GDPR a lot of folks are focusing on just their website, but GDPR covers more than that. It's a business issue, not an IT one. It affects IT, for sure, but it goes way beyond that. However, for most businesses, it's their website that will be the first port of call for potential customers. So it needs to be right so it sends the right message. More and more customers, as time goes by, will become savvier about what their rights are and what is expected from consumers of their data. Yes, it's can seem quite a painful paradigm shift.

The Whats, Whys and Wherefores

In the end, it simply makes good commercial sense to be seen as a business that can be trusted by being one that cares about their customers and their data.

The truth is there is that, right now, there is so much misunderstanding about the GDPR (General Data Protection Regulation). This is causing confusion and panic. Take a breath and just get started. You may not get it all done by the time it comes enforceable from on 25 May 2018, but that's not the end of the world. Having a clear plan of your intentions (even if after 25 May) will go a long way with the regulators if you're targeted. So get started, and plan what you're going to do.

I'm not a lawyer, but I have had a lot of experience dealing with GDPR for a number of organisations. That said, every organisation is different and I always insist that they each still seek legal advice regarding their GDPR intentions/plans to confirm that they are in fact legally correct in their case. So you need to ultimately do that too!

GDPR is a big subject, but for the most part not nearly as difficult as many people think. I hear all the time, "I just need someone to tell me what to do". Well, a short while ago Mike Killen (of Sell Your Service) asked if he could video an interview with me for his clients to cover just that. That is, just give some straight and practical advice. I was happy to do so, and that video is below.

One point of note: Mike specialises in selling sales funnels to clients, and also training his clients to do the same with their clients. So this video was targeted at funnel builders, however, in reality, everything covered applies pretty much to any website. So, if you're one of those "just tell me what to do" people, then this video is for you. I hope you find it helpful.


If you’re truly serious about getting ready for GDPR, make sure you check out our GDPR checklist (see below). It’s a great infographic that identifies the main areas that you need to focus on (not just the IT stuff). Of course, if you have any questions or comments about this post, please feel free to add them to the comments section at the end of this post.

gdpr elements graphic

Worried about what's involved with the GDPR?

Disclaimer: This post is not legal advice. So ensure you check your specific GDPR circumstances with a lawyer.

TL;DR: The GDPR is a regulation that activated and became applicable on 25 May 2018. It changes how businesses globally handle the personal data of European individuals (whether online, digitally, or with hard-copy). This affects non EU-based sites and businesses too. You need to make your business and websites GDPR compliant, otherwise, you could be facing some serious fines!


Why should I care about GDPR?

To be honest, small, medium, big or huge businesses – it doesn’t really matter; all sizes of businesses should be scared. The reality is that bigger businesses are more likely to be able to tolerate any fines levied if they fall foul of the GDPR (and they can be huge).

But I’m getting ahead of myself.

So, what’s the big deal?

Well, to answer that we need to know what the GDPR is. This next bit of background adds a little necessary context, but bear with me.

GDPR stands for General Data Protection Regulation. And the GDPR will replace the Data Protection Directive (DPD) of 1995.

A brief history lesson is this:


The GDPR allowed for a two-year transition to allow businesses to get ready for it. This means it became applicable on 25 May 2018.

For those that care, unlike the DPD, which was a Directive, GDPR is a Regulation. Which means it's already law. It doesn't require national governments to pass any enabling legislation (as was necessary to make the DPD law, by passing the DPA). In other words, and like it or not, it’s live now.

The GDPR is an EU law made up of a bunch of Articles. They cover things like scope, definitions, liabilities, remediation’s, penalties etc. All of the member states of Europe have a Supervising Authority (SA) that will advise and enforce the GDPR in their region. In the UK, the SA is the ICO.

Whilst all member states have agreed to the GDPR, each member state can add to it if they wish for their region. Germany is one such member state. The GDPR is tough as it stands but Germany is adding a bunch of extra rules, making it even tougher. So if you have data stored and / or processed in Germany, you may have even more hoops to jump through.

The full 88-page Regulation can be read by all and sundry by visiting the Europa website.

There’s also lots of other helpful (and easier to read) information surrounding GDPR on the ICO website. Definitely worth checking out.

So why would the ICO come knocking at your door? Well, if you have been wronged (from a data perspective), the ICO are the organisation you complain to. For example, you're still getting emails after unsubscribing from a list. Or you have asked an organisation what data they hold about you - and you get no response. The ICO has stated that they intend to process 100% of all complaints made.

It is worth noting that it matters not whether the UK is in or out of the EU. The GDPR will still apply. That said, post-Brexit there will likely need to be some tweaks to how it is applied.

Yeah, okay. So what is the GDPR already?

The GDPR is not too dissimilar to its predecessor, the DPA. The DPA concerned itself with how organisations, businesses or the government use personal information. Under the DPA, those responsible for using data of this type are required to adhere to strict rules (known as data protection principals).

Ok, fair enough.

The GDPR takes those principals further and wider. Meaning the ICO have the power to levy much more significant fines for non-compliance. Some items in the DPA that were just recommendations have now become fully mandated. So, the key thing that businesses need to understand here is that the GDPR has a lot more teeth, and bloody big ones at that.

If businesses ignore this law, they can be fined up to €20m (Euros) or 4% of their global annual turnover (whichever is greater). In some cases, a business can actually be shut down!


Compliance will need a lot of time and effort from businesses. Many, many businesses are only now just beginning to realise what a mammoth exercise this is. And time is running out...

Of course, that all sounds like doom and gloom - and for businesses, it isn't going to be fun or a cheap exercise. Yet, we mustn't overlook the huge positives that the GDPR will bring to us as individuals. For us, the GDPR is actually an immensely good thing indeed. And very long overdue.

So what does the GDPR cover?

The rules are pretty complex, and it is easy to find them overwhelming. It’s mostly common sense really. The rules fall into six main principles.

Personal data must be:

  1. processed lawfully, fairly and in a transparent manner in relation to individuals;
  2. collected for specified legitimate reasons. And then used only in ways the individual concerned is clearly aware of and agrees to;
  3. limited to only what is necessary, in relation to its use;
  4. accurate. Where necessary, you must take every reasonable step to ensure that such data stays accurate
  5. regularly reviewed to confirm it remains necessary to have the data. Erase it without delay if it is no longer necessary;
  6. stored and processed in a secure manner through appropriate technical or organisational measures.

Some definitions

Personal data under the GDPR is defined as data that can be used to identify a European individual. This is regardless of where – globally - that data resides. Personally identifiable data includes obvious things things like:

Perhaps less obvious (but now well and truly in scope) are things like:

The list is pretty extensive should you go look at the regulation. Pretty much anything is fair game as personal data if a European individual can be identified by it.

Three other key definitions that crop up throughout the GDPR that you will need to be familiar with are:

Bear in mind that a person, organisation, or agency can be both a Controller and a Processor.


The scope of the GDPR is defined in two ways - Material and Territorial:

Material - In scope:

Personal data that is:

Material - Out of scope:

Using personal data:

Territorial scope:

As you can see, the definition of what is personal data is much broader than before. And the GDPR has a much greater territorial reach. A global company that has EU personal data stored in the US, for example, is in scope and is liable!

What about Public Domain data?

The GDPR still applies when the source of the data was public domain (and so was freely available). Largely, the rules here are to do with the use of the data, and whether explicit consent becomes necessary. Using such data for profiling is an example where the GDPR has a greater effect than before.

Key Rules

Just a few of the key rules that fall out of the six main principles, described earlier, you'll need to get to grips with are:

So what do I do now?

If you haven't started to act then you need to start now.

This is an immense undertaking for the majority of businesses. It will require many (if not all) existing business and IT processes to be reviewed and changed. It will affect business websites and how they collect and / or process data. It also affects all agreements / contracts where personal EU data is shared. This is whether it’s just for consumption or for onward processing.

And finally, businesses will need to have agreements drawn up with entities within their own organisation if such data crosses country borders. And those agreements will actually need to be logged with the SA for that country.

Below this post you can download our check list on how to go about getting compliant for the GDPR.

If you need help with GDPR, please contact us through the form on our contact page.

gdpr elements graphic

Worried about what's involved with the GDPR?

Elixir Web Studio is a trading name of YourScope Consulting Ltd.
Copyright © 2022 YourScope Consulting Ltd.
Top cross linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram