Parsing Stuff with Flows (Part 2)

Standard

In part 1, I built out the change of thinking that we will need in this blog post to amp up our data parsing using flows. For a quick recap:

  1. The scenario is that we have questions and answers
  2. The flow does the parsing by treating questions as keys
  3. We are using a text input in a flow to simulate the action of a user copy / pasting question answers into a text field

As demonstrated in the last post, this works within the context of a flow, but now in this post, I am going to show you how to apply this. To demonstrate this, I am going to add a text box onto both the lead record and contact record to receive data, two text boxes that will receive the parsed answers and a checkbox to display an error state. To launch this flow I am going to use a process builder on the lead and contact.

The process builder functionality is the same on leads and contacts. The ID will be passed to a variable in your flow. This variable is used by the flow to determine which update action to use. The input is also passed over to a variable. This does mean that for those following along at home that they will need to change their formulas from using a text box to using the formula. This is in addition to the changes needed to make it an autolaunched flow (Removing screens, etc).

Now, I did mention the whole error checking thing in my last post, so baked that in as well. The key here is to first check for errors THEN figure out which record needs to be flagged.

The end result will be something like this:

with error check

So, how does this work? Fan-Tas-Tic. With just two processes and a flow, I am able to do parsing on each record.

end results

Adding this parsing logic to a new record would just be adding a new process and updating your flow. This is a great example of how you can use flows to harness the power of apex with the ease and lower support cost of configuration.

Now, this is setup for a pretty specific example…A rep would be pasting in data from an external source, but the methodology would be the same as long as you had a source of text. So, with tweeking you could use this on fun stuff like inbound emails or maybe even chatter posts!

How does it feel? Not quite like this, but close.

I have the power.gif

 

 

Parsing Stuff with Flows (Part 1)

Standard

Salesforce is really good at a lot of things, but digesting or looking for bits of data within large chunks of text is not a particular strong suite, though to be fair, not may systems can brag about how awesome it’s parsing ability is. I was thinking about this subject since there seems to be two camps, the configuration camp backing workflows and formulas and the code camp backing apex. I am going to propose a bit different way…an adminveloper way.

To start with, we are going to use flows for this. The reason I am going to use a flow is that I want this as object agnostic as possible and I don’t want to be constrained by any of the formulaic limitations (Looking at you char limit of related formulas!). Using a flow will also let me do some fun stuff later on (cough, next blog post, cough), but the biggest reason I want to use flows is the variables.

But, before we get into the nuts and bolts, I need to first talk about how I changed my thinking about this. Let’s say I have some questions in a text field and I want to parse out the answers to these questions. In the past, I might have tried to hard code in some right / left functions, but that is rigid and leads to stuff like “Answer this question in less than 255 char…”, ugh. Instead of trying to build out left / right stuff that ignores questions, you need to think of questions as keys in your document. They are a unique set of text / numbers that should only occur once in your doc, and because we are thinking like this, we can use the FIND function to locate their specific points within the text.

For testing purposes, I am just building out a basic flow with a long text input field that will be parsed.

The flow will look for my “keys” (AKA, questions) and determine how much distance (in char) between the LAST CHAR of a question and the FIRST CHAR of the next question. For the last question, we are going to use a footer as the marker (“Thanks for your time!”).

I am going to do this with a series of formulas, one for each question:

  1. Find out how long the whole piece of text is (This is just a LEN(your text here), not going to expand it out.)
  2. Find out where each question ends
  3. Find out how long each answer is
  4. Build out the answer

Formula number two is finding out where the questions ends. To do this, you use the “find” function, looking for the variable within your text. Now, you need to ADD to this the length of the question since you are looking for the END of the question and FIND returns the char location. Here is what the formula looks like:

find({!varQuestion1},{!Enter_Sample_Text_Here})+len({!varQuestion1})

Now that we know where the first question ends, we need to find out how long the answer is. We do this by subtracting the value from the first formula from where the value of where the next question (or text) starts. I did it this way, though you could have also just used a new find function. In a nutshell, at this point, we have determined that the end of question 1 is X and the start of question 2 is Y and that the answer is Y-X long.

({!FindQuestion2}-len({!varQuestion2}))-{!FindQuestion1}

Knowing this, we are going to go ahead and build out the formula that strips out the answer from the text. It is going to use a combination of left and right functions. We are essentially grabbing all text to the RIGHT of the end of question1 and then taking just LEFT text of that in the length of the Answer

left(
right({!Enter_Sample_Text_Here},{!GetLen}-{!FindQuestion1}),{!Question1Length}-1)

For the last question, you would just use the footer location:

{!FindQuestion4}-{!FindFooter}

FindFooter = find(“Thanks for your time!”,{!Enter_Sample_Text_Here})

This is how this function would look just running it from a flow:

So yeah, with just a few formulas inside of a flow, parsing can be easy – peasy if you adjust your thinking. Now, before I leave you all hanging for part 2 of this blog post, let’s also take a look at something fun. What happens if someone starts to monkey with the questions? Well, through a little bippity boppity boo we can do something about it, without any more formulas. See we are using the FIND function already in the first formula that finds the end point of the question…and if the find function doesn’t get a match it returns a zero, thus, we know that if the formula that finds the end point of a question returns the length of the key variable something is off. This can be done with just a decision!

Alrighty, that is it for now! Part 2 is going to expand on this FUNctionalitye even more, so stay tuned!
As always, let me know if there are any questions / comments / or you just want to buy me coffee and pick my brain.

 

 

Smarter Text in Flows

Standard

As Salesforce admins, I hope you have figured out that Flows can make your system super smart. I think this is a smart little hack to flows that can help make them even smarter!

Hopefully not this smart

Here is the setup. You have a flow and in this flow there is some data that is stored in variables. Because this data wants to go forth and adventure, you might use a text template to put some, well, text around those variables so that it makes sense. The text template would then be used in an email alert (just for example).

The thing is, as we all know, the minute you get the text of ANYTHING dialed in, someone asks for it to change. So, into the flow you go, modify the text template, save a new version, etc, etc, etc.

But, what if there was a better way? That question was rhetorical, since there totally is a better way.

For this blog example, I am just going to have a two screens, one as a starting point and a final screen that will substitute for the above mentioned email alert.

flow overview

No clever caption for this

Notice, there is NO text templates in this flow.

Look - No Text Templates

But, the end screen has all this text? WHAAAT?

Final Product

And, just to prove I am not pulling a fast one, here is what that field looks like…it is just variables.

and just to prove...

Instead of using a text template, I am using a text field on an object. The trick here is that you have to enter the variable technical names (Curly brackets, exclamation points) into the text field. This text field is then pulled in the flow via the record look up and will accept the values from the variables.

Really, this is acting JUST LIKE A TEXT TEMPLATE, but with the advantage being that if you want to modify the verbiage you don’t have to go through the modify / save as / activate cycle.

But, we can make this EVEN BETTER! Obviously, having to enter the technical variable name limits how many people can actually use this. But, by adding a bunch of code…LOL, just kidding. We are going to build out a formula field instead. You have to do some gymnastics to get the formatting to work, but once you have it built out, you now have a formula that will show up on the actual records itself and used just like the text field above.

formula           formula on screen

And, the end result is the same!

automagical results

 

so, what do you all think? useful? not? any suggestions? I even take requests if there is a weird question (about salesforce) you might have.

 

Fuzzy Searching in Salesforce Flows

Standard

Salesforce flows are a magical thing, like good coffee at work and unicorns.

coffee unicorn.jpg

This is how I want my coffee delivered.

 

I have come to realize that there are limits to even the most magical things (BOOO!).

The limitation I have found in flows is around how you search for records…but, let me be clear, it really isn’t a big deal. For most people, finding records using the typical “equals”, “contains”, “starts with” and “ends with” functions will work just fine. I however, found myself going down a path where that wasn’t going to quite cut it. The challenge is how to search on a text input in a manner that is more google like. I don’t know what the kids now a days call it, but back in my day, we might call if “Fuzzy Matching”.

Fozzie_bear.png

Fuzzy, Not Fozzie!

For example, let’s revisit my Jaeger Dispatching System (Special Note, Pacific Rim 2 is scheduled). This system uses dynamic drop downs for the Jaegers, but, what happens when you have a bunch of Jaegers’?  You can build out a record search based on a text box, but, as mentioned before, you are limited to “equals”, “contains”, “starts with” and “ends with” functions. At this point, you might be saying, fine, just use a “contains” operator…and that would work, except what happens when the user spells something wrong? Contains is just two wild cards, so if you entered in “Dangur” instead of “Danger” you would not get a hit.

 

What happened next is pretty funny. I started thinking about how there are patterns in words…and then started thinking about how the pairs of letters could work. Spoiler alert, it totally worked. I proved it in Excel by just using a vlookup and some formulas, so I got pretty excited. It was then that I googled this matching pairs thing and found out that yep, some one wrote about all the fancy math behind it.

http://www.catalysoft.com/articles/StrikeAMatch.html

So, after building out the proof in Excel that this would work, I set about trying to get this to work in Salesforce…specifically a flow. I want to be able to enter in some characters into a text box and see returned results based on how well they matched my search term.

The first thing I did is create a field that removes the spaces from the Jaegers’ names and made them lower case. I don’t want it being “Cherno Alpha”, I wanted “chernoalpha”. This is done via formula field. If doing this in real life, I would build out my formula to also remove punctuation, but this is just for my Jaeger dispatch and my blog, so I am just removing spaces.

Thus, concludes the non flow part of this blog…what follows next is like 100% awesome, you have been warned.

TAKETHISCAT.jpg

Woot! FINALLY got to use this meme!

The first couple things are pretty basic, I have a start screen that has a text box. Next, I have a fast lookup on my Jaeger object. This gets all the Jaegers and puts them all in a collection. Next up is my loop, where I go through each Jaeger record. The only “gotcha” is that when you do the fastlookup, you need to bring over your formatted text from the record. Screen shots of this would be pretty boring, so here is a picture of all the giant robot toys.Jaeger Toys.jpg

Within the loop, I start with two assignments that copy the formatted Jaeger Name (no spaces) and the search string to variables.
I am going to use these variables for the rest of the functions, including the formulas. I take the search string that was entered and format it up.  I remove the spaces, count how many pairs I have and if the value has a remainder, I also remove the last character. I do this because otherwise the matched pair logic would be searching on a single digit, which would skew the results. The formula also checks if the search string is just 3 char, and if it is, it will treat these three char as one “pair”. Pictures and Text!

Formatted Search String

if(len(substitute({!Search_String},” “,””))<>3,
if(
mod(len(substitute({!Search_String},” “,””)),2)<>0,
left(substitute({!Search_String},” “,””),len(substitute({!Search_String},” “,””))-1),
substitute({!Search_String},” “,””)),substitute({!Search_String},” “,””))

Now I have to compare my first matched pair to the formatted name. of the search string that was formatted. I use a formula to get my matched pair:assignment - formatted search string.png

if(len(substitute({!Search_String},” “,””))<>3,
lower(left({!varSearchStringUseCopy},2)),lower(left({!varSearchStringUseCopy},3)))

 

The flow will next do a name check via the decision function. If the Formatted Jaeger Name contains the current matched pair, the flow adds a value of 1 to the counter variable and adds the current pair to a variable that will show the matches and the ID of the current record to another variable. Ugh, that was hard to read, here is a picture:assignment - match found

If the pair is NOT a match, well, I don’t really do anything with it but you might want to shove it to a debug variable. In fact, if you are starting this from scratch, I would HIGHLY suggest you do this!

Next up is yet another assignment, this time though, we are removing the pair was just searched on. This is done with, you guessed it, a formula:

if(len(substitute({!Search_String},” “,””))<>3,
substitute({!varSearchStringUseCopy},left({!varSearchStringUseCopy},2),””),substitute({!varSearchStringUseCopy},left({!varSearchStringUseCopy},3),””))

remove search string

Once that is completed, we check to see if there are more pairs to check. This is done by looking at the number of pairs left after the current pair is removed. This is in a formula I like to call “DisappearingSearchString”:

len({!varSearchStringUseCopy})

The whole process looks like this:

match process

If all the pairs have been used, the flow then checks to see if there were any matches with a decision point on the counter variable. If yes, then we add the matching data into a variable and then start the loop all over again. Because we will want to display some results in a table like format, be sure to append a text template that has a line break at the end of the string. To do this, create a text template with <br> in it.

build out result line.png

One of the things I really wanted was a way to see how many of the pairs were found in a given record. I do this with this formula:

({!varTripCount}/{!frmSearchStringPairs})*100

 

Before the loop starts all over again, any used variables are reset:

clear counters.png

So, enough talk! Let’s see how this works! For comparison purposes, I put in an alternate lookup that will use the “Contains” search function of what was entered in the input.

I also added more Jaegers, 8 in total!

Jaeger List.png

boom

 

First search string is going to be “Eureka”:

Eureka.png

and here are the results:Search Results - Eureka.png

The “Contains” function did what I expected and returned two records, “Striker Eureka” and “Eureka Smack”. However, it did not find “Striker Eurek”, but the matched pairs function did!

Let’s try this on another scenario. Suppose there is someone new in the Jaeger Dispatching Center and they forgot that it is “Cherno Alpha” and they enter in “Alpha Cherno”.

Search String.png

The “contains” search function would literally return ZERO results, whereas the matched pairs function would show an 80% match with Cherno Alpha.Results - Cherno Alpha.png

So, there you have it. With a bit of work, you can do fozzie…err…fuzzy search results with in a flow with Zero coding!

As always, if you have any questions, comments, or suggestions, please let me know!

Andrew

Reducing the amount of email while sending email

Standard

In my post titled “Cleaning the data that matters – and not all data matters” I finished the post up with the following:

“PS – For bonus points, create a nice email alert telling the reps their data is bad, and make it so it sends them that notice every time they edit the account OR opportunity…just put on a timer so it only sends once per day!”

To which, JaneIsaac replied:

“nice detective work. Could you share What the timer formula look like?”

Well JaneIsaac, this post if for you!

Not that type of request

I take requests…just not freebird!

The scenariois that we wanted to send out alerts if an account scored low data grade points and that account OR an opportunity related to that account was updated. After some quick research I saw that the updates were clustered, often receiving multiple updates in a short period of time. I didn’t want the alerts constantly kicking out.

So I built out a function so that prevent multiple alerts from being sent out in a given set of time. My functionality treats account and opportunity updates as two different actions, so I broke them out on this blog as such. Listing out the ingredients below and I will dissect the basic functionality after.

Must be about snack time...

Ingredients for tasty food, not tasty Workflows

For the Account alerts:

1 – Date field on Account “Data Alert Sent Date”

1 – Workflow rule for the Account Object “Data Grade Alert”:

Evaluation Criteria = “Evaluate the rule when a record is created, and any time it’s edited to subsequently meet criteria”

Rule Criteria =

Account WorkFlow Criteria

AND(
AND(Account_Data_Grade__c <>”Acceptable”,Account_Data_Grade__c <>”Excellent”),
Open_Pipeline__c < 1,
AND(LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “, LastModifiedBy.ProfileId <>”xxxxxxxxxxxxxxx”),
(DATEVALUE(CreatedDate)<>Today()),
OR(ISBLANK(Data_Alert_Sent_Date__c),(Data_Alert_Sent_Date__c) <> today()))

2 – Immediate Workflow Actions

All about that (Account Workflow) action Boss

1 – Workflow email alert Sendemail to “Last Modified By”

Account Workflow Alert

       1 – Field Update “Data Alert Sent Date” with Today()

Account Field Update

 For the Opportunity alerts:

1 – Date field on Opportunity “Data Alert Sent Date”

1 – Workflow rule for the Opportunity Object “Data Grade Alert”:

Evaluation Criteria = “Evaluate the rule when a record is created, and any time it’s edited to subsequently meet criteria”

Rule Criteria =

Opportunity Workflow Criteria

AND(
AND(Account.Account_Data_Grade__c <>”Acceptable”,Account.Account_Data_Grade__c <>”Excellent”),
AND(LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “, LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “),
Record_Type__c =”Open Opportunity”,
(DATEVALUE( Account.CreatedDate )<>Today()),
or(ISBLANK( Data_Alert_Sent_Date__c ), (Data_Alert_Sent_Date__c)<>TODAY()))

2 – Immediate Workflow Actions

All about that (Opportunity Workflow) action Boss

1 – Workflow email alert Send email to “Last Modified By”

Opportunity Email Alert

          1 – Field Update = “Data Alert Sent Date” with Today()

Opportunity Field Update

Taking a look at the mechanics:

I wish my cube was this cool...or that I had a flying monkey!

I wish my cube was this cool…or that I had a flying monkey!

The rule criteria’s are similar enough that we won’t have to dissect them both and since the interest is in the timer components, that is what I am going to focus on:

1)      (DATEVALUE( Account.CreatedDate )<>Today()) –  Ignore if the account is newly created

2)      But, the following situations are OK:

  1. (ISBLANK( Data_Alert_Sent_Date__c ) – The data alert sent date is Null (Never triggered before)
  2. (Data_Alert_Sent_Date__c)<>TODAY() – The data alert sent date does not equal Today()

This last line is what ensures that an alert will only send once per day. If the rule runs, (Data Quality = Poor and “Data Alert Sent Date” <>Today()), then the email alert gets sent out and the “Data Alert Sent Date” gets updated with the current day. If that record was updated ANY OTHER TIME during that day, the rule will not fire. I know I say this all the time, but what I really (Really) like about salesforce is that when it comes down to it, you can do some crazy cool stuff with zero code.

Clicks Not Code!

In other CRM’s, the above functionality takes 6 weeks and 2 developers.

 

Looking at this functionality now, I think a couple neat additions would have been:

1)      A rollup summary on opportunity.Data_Alert_Sent_Date__c (MAX), this way, you could have the account rule also looking at the last time an alert was sent out on ANY opportunity.

2)      A counter field update on the opportunity rule with a corresponding rollup on accounts. This would allow for reporting on ignored updates and thresh holding of the alerts.

But, the fun with Salesforce is the ability to rapidly prototype and tinker, so if I wanted to add in some new stuff, it is easy – peasy – lemon squeezy.

Well, hope you enjoyed this. I certainly had fun taking a look at something that was built out quite some time ago but continues to keep ticking! If there are any special requests, just let me know!

Cleaner Page Layouts using Flows and Formulas (1 of 3)

Standard

Back in the day, when I was just a transfer student at Everett Community College, “one week” was a hit single and I was a newbie coder taking visual basic.

(Your welcome for this ear worm)

During this class, we had a discussion on page layouts, that went a little something like this:

If you design a layout that has a bad tab order, and it reduces the speed of a transaction by one second, is it a big deal? Well, consider it this way: If your software is bought by a million people, and they can complete 500 transactions a day, your one second reduction of efficiency is costing the consumer 500000000 seconds per day…which is 8,333,333 minutes or 138,888 hours. If the average wage of those users is ten dollars an hour, your one second in efficiency now has cost 1.3million dollars per day.

Not even a Lego Calculator could make that discussion cool

With guilt trip thusly set to “argh”, I focused my efforts on UI design and making things work efficiently. Even now, I can remember the tab order of one of my first CRM’s I worked on…because it was out of order.

The stakes have changed since I was taking Visual Basic. I (we) support sales, and lost productivity is not simply about lost time, but about what your sales teams COULD have been doing. The math is pretty easy…and pretty scary:

Time spent clicking / scrolling / using salesforce in an inefficient manner

X by Number of times

X by Number of Users

X by days in year

= Time wasted = Money Lost = No free coffee

For the sake of this blog post, I am going to clean up the contact layout. I have sat with my users and estimated that they waste about 2 seconds every time they hit the layout  because of a section that Marketing has requested. This section consists of four check boxes, three text boxes and one URL field in a two column layout. This section was created for marketing and was placed near to the top of the layout in return for the data not being required. This section pushed a much more used section down below the scroll line (IE, users would have to scroll to see it). Marketing has given the OK on making this section not visible as long as there is some visual refernce to these fields still on the page layout.

A user will typically hit the contact layout 25 times per day and I have 25 users. If I can compact the layout, I should be able to reduce scroll time by about half, which should save about 45 (sales) hours per year. Notice, I didn’t just say hours, I said sales hours. Sure, saving 45 regular hours might not be much in the whole scheme of things, but sales hours is like a force multiplier. If you enabled your sales teams to have even a few more minutes per week, they can make a few more calls, make a few more emails, make a few more dollars.

Take a minute to enjoy this worn out cat.

Phew

I am beat just writing about this!

I am going to break this whole thing out into three distinct chunks:

1)      Create the Summarizing Formulas (In this blog)

2)      Create the Visual Prompts (Next Blog)

3)      Make Data Entry awesome with Flows (Next Next Blog)

Summarizing Formulas

Personally, I tend to write smaller, nested formulas that analyze bits and pieces of data. This makes it a bit easier (in my opinion) to write that final formula that presents the results to the user. While you could probably write this all in one huge formula, for the sake of troubleshooting and scalability, I am going to create the following fields:

1)      Create a formula to look at the 3 text fields (Return Type is Text)

Text(

if(len(Test_Text_1__c)>0,1,0)+

if(len(Test_Text_2__c)>0,1,0)+

if(len(Test_Text_3__c)>0,1,0))&” out of 3 populated; ”

Text Box Formula

2)      Create a formula to look at the URL field (Return Type is Text)

if(len(Test_URL__c)>0,”URL Present”,”URL Not Present”)

URL Formula

3)      Create a formula to look at the check box fields (Return Type is Text)

Text(

if(Example_Check_Box1__c=TRUE,1,0)+

if(Example_Check_Box_2__c=TRUE,1,0)+

if(Example_Check_Box_3__c=TRUE,1,0)+

if(Example_Check_Box_4__c=TRUE,1,0))&” out of 4 set to True; “Check Box Formula

4)      Create a formula to aggregate the above

Check_Example_CheckBox__c &” “& Check_Test_Text__c &” “& Check_Test_URL__cAggregate Formula

The net result is a field that will present the user with data facts not data entry points. Aside from having a cleaner layout, I a firm believer that if presented with text, most humans brains at least acknowlege that text before moving on. By reducing the clutter, you are making your overall page layout less fatiguing.

End Result

Individual Results

In the next post, I am going to discuss how we are going to visually prompt the user to give us data, but until then consider the other benefits of this type of functionality:

1) You could use these fields in reports to give better summaries

2) You could write validation rules off of these formulas rather than the individual fields

3) You could write workflows off of these formulas

See you all next week, same BatTime, same BatChannel where I will show you all how to kick it up a notch and grab your users attention!

Kick it up a notch

You totally thought I was doing Batman pic, weren’t you?

Andrew

Cleaning the data that matters…and not all data matters!

Standard

In my previous post, I alluded to a list of 5 concepts that make data cleansing a bit easier (Not fun, not easy – peasy but easier). In this post, I am going to expand on the concepts of “Knowing your data” and “Classify your data”

It's about half the battle

GI Joe talks about knowing

.But, before we get into the methodology and the doing, let’s talk about tools used. We are actually only using two tool to build out the functionality found with in this post, reports and formulas. However, because the methodologies discussed below is different than most organizations approach to cleaning data (Ocean…Boiling) there will be work on you to get folks bought into the ideas of not just trying to clean everything. So, I guess if you want to get technical, a third tool is the soft grey matter inside your noggin!

First things first. To help me “Know” and “Classify” my data, I am going to write a report that has two bucket fields, “Customer” and “Pipeline”. The bucket fields are looking at two custom field that are rollups counting the number of booked opportunities and the number of open opportunities. These are my two primary classifications because I am going to use a combination of these two classifications to score the value of an account to my company.

1)      Non Customer, No Pipeline (Least Valuable)

2)      Non Customer, Pipeline

3)      Customer, No Pipeline

4)      Customer, Pipeline (Most Valuable)

My fictional org for “Kramerica” wants all 481k of their accounts cleaned. Before jumping in and just starting to cleanse, I set up a report that breaks down an account based on past purchases and pipeline. Just by using two bucket fields, I can see that 14,000 accounts (About 3%) that are high value (Customer with Pipeline), 13,000 (3%) are medium value (Non Customer with Pipeline) and 54,000 accounts (11%) that are medium value (Customer No Pipe or Non Customer Pipe). I have just reduced the pool of accounts that should be cleansed by nearly 83%.

Numbers don't lie

Dry those eyes, it is not as bad as it seems

Unfortunately, there is still a number that is not very friendly standing between us and Maragriatville.

Margaritaville is real, google maps told me!

Which is just outside of Dallas apparently.

So, we are going to take things up a notch and write a set of formulas that will score the data that is entered on our account records. The folks in charge of data management (and that might be you), decided that Address, Phone and Website were most important. Yeah, I didn’t put state / country, but that is because of the change making it a picklist field, and we will just assume Kramerica is using the picklists. I am going to end up creating four formula fields. Three formulas will look at the data contained in the three fields. The fourth field will sum the scores of the three fields and then based on the totals, grade the data “Good”, “Acceptable” and “Poor”. The formulas don’t have to be complex, even something basic like if(len(FIELD=0,1,0), which will check for the presence of any data in those fields.

Just the ones that matter

In this case, red is good because red = less work!

That was a fun diversion, now, go back to the original reports with primary / secondary classifications. We add in the data grading field. Now, you can see how many of your most valuable accounts actually need the most help. In the case of Kramerica, we want to distil down that 14% (68k accounts) even further so we can focus on valuable accounts that have a data score of zero (no values in any of the fields) or one (at least one field has some data in it). Applying the formulas and the buckets to my data set reduces the amount of accounts I need to look at from 54,000 to 18,000.

I think this deserves a quick, bullet pointed recap:

–        Initial data set, 480k accounts

–        Valuable Accounts:

o   Customer / Pipeline (Most) 14,000

o   Pipeline / Non Customer 13,000

o   Customer / No Pipeline 54,000

–        Data scoring of valuable accounts:

o   Zero data score = 5,000

o   One data score = 13,000

–        Reduced my “need to clean” by nearly 90+%

My SFDC admin is amazing

I get this way whenever I shake loose a bit more time in the day.

Yeah, that is pretty awesome. However, there is the question of what do to with all those “other” accounts. Here is where it goes from awesome to AWESOME (in a monster truck voice). Since you have already established what makes an account valuable, once an account meets a certain threshold (gets pipeline), you know that it then needs to be cleaned up…and of course, you know what needs to be cleaned up because you are already scoring it.

2014-06-01 20_51_21-awesome monster truck - Google Search

 

PS – For bonus points, create a nice email alert telling the reps their data is bad, and make it so it sends them that notice every time they edit the account OR opportunity…just put on a timer so it only sends once per day!

Don’t start cleansing data yet!

Standard

Data is a fickle beast.

One minute, you have amazing dashboards and reports… your finance nerds are seeing into the future with clarity a weather man can only wish to have…the next minute, you have gremlins everywhere causing chaos in the most basic of processes and you can only give accurate forecasts for five minutes in the past.

Don't feed data analysts after midnight!

All your data are belong to us!

I suspect this has been happening since mankind developed the first CRM, which was on Oracle Clay Tablets.

Oracle V1

You should see the servers needed for this!

Having been on many data cleansing projects in the past, with many more in my future, I decided to sketch out some ideas I have picked up along the way. Don’t worry, I will go back to my techie salesforce nerd stuff next week!

“It is a never ending story”

Cleansing data is not a project with a start and an end, it is a process that needs to be ongoing. If you have data coming in, you will have data that needs to be cleaned. Build it into your budget, chant the mantra, do whatever it takes, but embrace the fact that as long as you are around any CRM you will be doing data clean up.

“Business Involvement”

Even though dirty data and data cleansing will never go away, it will become a smaller task once you get your users sold on the idea of clean data. At the very least, you need your users to care about the system at the best they will become advocates of clean data. Boeing used to have a program called “FOD FREE”. FOD is “Foreign Object Damage” and it prompted their employees to be active in keeping the work environment clean. It was a huge success through marketing and  engagement, AKA, Business Involvement.

“Clean with a Purpose”

There are two methods to getting business involvement in data cleansing, carrot and stick. Personally, I prefer the carrot approach. Know why you are doing it, and be able to explain that to the business. Tell them in “What’s In It For Me” (WIFM) terminology why their data is changing and what outcomes they can expect. Have them involved in any process modifications or validation rule building. If you get them at least interested in clean data the process will be much less contentious.

“Know your Data”

Seriously, run some DANG reports. Know the numbers because someone will ask. Know the up and downstream impacts of dirty data. Know use cases. Have a really nice power point set explaining this things, and gear the presentations to different user levels. If you do not  know your data, how can you clean it???

On a side note, I swear by “You suck at powerpoint” as a great learning aid around presentations!

“Classify your Data”

Classifying data is just chunking up your data into sound bite groupings. The key here is “Sound Bite”. You can say something awesome like “Customers with an account that has at least 3 contacts that all have been sent an email in the past three years”, but after the first couple words, all anyone will hear is “blah blah blah”. Instead, have sound bite ready classifications. Thinking in “Sound Bite” terms will also help with reporting and formula writing, covered next week!

Here are some suggestions for accounts:

Primary = Customer, Non Customer

Secondary = Active (Open Pipeline), Non Active (No Pipeline)

Tertiary = Marketable (Contacts with Email), Non Marketable (Contacts without Email)

It’s looking a lot like Christmas (Sigh)

What really gets me excited about classifications is that it helps you NOT boil the ocean. It is not unrealistic to have hundreds of thousands of account records, and if you were to set about trying to clean them ALL, you would be wasting time and money on records that really are the equivalent to that fruitcake you got last year. It is just taking up space, but you don’t want to throw it out because someday you might have a reason to use (re-gift) it.

fruitcake

Yes, I did just compare your data to an old fruitcake

The above tips are not the end all be all, just things I have picked up along my career. But, if you are rolling into the discussion on data clean up just keeping these in mind you will be at a point where you have the business engaged in the ongoing process of data cleansing on a known set of data that involve a set of agreed upon classifications…or, in other words, you will be setup for success!

Oh, and now that this stuff is out of the way, we can get back to more techie stuff next week!

 

Andrew