Search Results
83 results found with an empty search
- How I Solved It: File Deletion Flow
I know I'm not the only one that thinks it's a pain to work with Files in Salesforce. Stories of frustration, confusion, and downright bafflement abound. The object structure for what seems like a relatively simple and convenient File uploader on the page layout is anything but simple under the hood. ContentDocument , ContentDocumentLink, ContentVersion, ContentHistory, ownership, permissions, ... The list of considerations just keeps going. I could probably try to write a post explaining it in simpler terms but, frankly, I don't think I really understand it, so I would probably just lead you astray in some way. But I recently built something that turns out to be surprisingly simple and solves a common problem with Files, so I'm going to share that with you instead. The Business Problem Lots of organizations use Files in Salesforce, usually in the ways you would pretty much expect. You're working with a record, there is some kind of file related to that record, so you upload it for easy access and reference. This could be a photo of a contact, or a signed contract, or a mail-merged letter generated from the record that you are going to send out to a constituent, or a million other things. Let me introduce you to For Pete's Sake (FPS), a great organization that works with cancer patients and their families to give them "a break from cancer," a respite experience in which they can be together as a family to bond away from the day-to-day of regular life. FPS does their program management on Salesforce. After a patient is nominated, FPS staff goes through a series of steps to "onboard" the person and their family and get them ready for the respite experience. Most of that work is done on a custom object called Onboarding. In the course of working with the onboarding record, we have various files, including online forms that the participant fills, a family photo the patient sends, and the like. A perfect use case for Files! I've been working with FPS for two years, but I think they were using Files before I came along. I'm not even certain their original Salesforce implementer taught them to do so, so much as that they may have seen the Files related list and adopted it organically. (For a while they were also separately uploading the files to Box.com, a bit of duplicative work that I'm not sure they could articulate the value of.) Several months ago I worked with FPS to regularlize some of their usage of Files and to implement some automatic document generation to replace documents they were manually creating from a Word template and then uploading to the onboarding record. So far, so good. Basic Files stuff. But with the automatic document generation, naturally, we started to find some cases where the "final" version wasn't so final. Perhaps the dates of a respite trip changed. Or perhaps some mistake in the onboarding record is noticed just before the "Final Letter" is about to go into the box being mailed to the patient. These things happen. And FPS was savvy enough to realize that generally the solution here is to just re-create the document and upload the new version, whether that's a manual process or the re-trigging of some automation. But in those cases, the incorrect file is still attached to the record. That's likely to create some confusion! When asked what was the "right" way to deal with this, I just told them, "Go ahead and click Delete on the original file." Silly me, assuming they had the same options I see. They have no delete option on the file! I delved into permissions, but that wasn't the issue. If the original file was uploaded by one person and someone else is now working on the record, they can't delete the old file—it's not a question of permissions. Files can only be deleted by the person that originally uploaded them (the file's "owner") or by someone with Modify All Data , like a system administrator. I was seeing a delete button because I have Modify All Data permisssions. I even confirmed that if I gave Modify All Data to one of the program coordinators, she then could delete. But I really don't want to give Modify All Data to people. (There's a reason we abbreviate it as MAD!) Besides the implications for data security, I really hate the user experience that we get when we have MAD, where even fields that are Read Only on the page layout show as editable. Let me note a few other things about this problem: It's not that Files (ContentDocuments) have some kind of sharing model. It's simply binary: You own the file or you don't. You have Modify All Data or you don't. Before I managed to solve the actual issue, this meant I had a workaround: Get people to tell me when a file needs deletion and I can do it as the sysadmin. Not exactly efficient or automated, but at least I can keep things clean. While it's ContentDocument that stores the file, it's ContentDocumentLink that relates the file to a record. If you delete the latter, the file is still taking up storage on Salesforce servers, if you care. (Maybe I shouldn't , but I do.) I've also learned, through much trial and [mostly] error, that the Content Whatever objects have other annoying limitations. The worst: You can't really access ContentDocumentLink in SOQL. You have to query for only a single ContentDocumentId . ( But if I already knew the Id, I wouldn't need to be querying! ) You can't really work with Content Whatever in the UI. Generally you can't add fields, there is no page layout, you can' modify the Files related list... You can't make record triggered flows on Content Whatever . (Even if you could, it's not like you could change the sharing in some useful way.) Community to the Rescue? As soon as I saw that Help article linked above I knew I was going to be in trouble. But there are some smart people in the Trailblazer Community! Maybe someone had solved this before? Further searching was only turning up more commentary on the problem, not much in the way of solutions. Eventually I posted some questions online and get traction on this Ohana Slack thread . Erik Lopez suggested that perhaps a screen flow could assign Modify All Data, allow a user to delete a file, and then revoke Modify All Data. Interesting... But the first thing I realized is that you can't actually put a screen flow onto a File. (There's no page layout nor Lightning Record Page for files.) My screen flow is going to have to go on the onboarding record. And that means the screen flow is going to have to present all the available files for the user to choose which to delete. Now we've run into a different problem. How I Solved It, v1 Thought work complete, I set about seeing what kind of screen flow I could build. Step One: spin up a sandbox just for this purpose. Besides being a general "Best Practice," this is going to have some additional benefits: I don't have to worry that I upload a bunch of files and they're going to take up storage forever. I can make a bunch of test Onboardings and put files on them without confusing users. I won't have any chance of deleting important files in production. Remember, above, that I said working with these objects in SOQL is a pain in the neck? If it's hard in SOQL, then it's not going to be easier using Get Records elements in flows. It took me a little bit of fooling around, but I eventually realized that the screen flow was going to pass in the record Id of the onboarding and I have to Get all the ContentDocumentLinks that attach files to that record . Then I'm going to show those ContentDocumentLinks in a datatable for the user to select which to delete. [And here's a surprising early win: I'm going to be able to use the standard component from Salesforce. As much as I love and appreciate the Datatable from UnofficialSF , I'm happy to be able to make this flow with standard components.] Sadly, even though my Get Records is set to "Automatically store all fields," I found out that none of those fields is the filename . Clearly the users need the name to select which is the right file to delete—the Id of the document is not going to be useful. It's not an option to add a formula field on ContentDocumentLink that spans to the file. I'll spare you the details, but suffice it to say that I tried everything I could think of to get that title to display from the ContentDocumentLink, to no avail. Eventually I admitted defeat and tried looping over the ContentDocumentLinks to get the related ContentDocuments. In the Wins column: This works. My datatable on a screen right after the loop (not shown) can show columns for the filename, owner, and creation date. Yay! But I'm executing SOQL within a loop, a rather big No No. That is not efficient and it runs a good chance of running up against governor limits . Side note: Realistically, I could have just taken the win and moved on. This screen flow is going to run only on records that have fewer than ten—often fewer than three—files attached. It will work. The extra computing power used is negligible. And the screen after the loop starts a new transaction with a new set of governor limits. But that pink element within a loop did not make me happy. How I Solved It, v2 Tip o' the hat, again to Erik Lopez who suggested that we could probably avoid the SOQL in a loop if within the loop we assigned the Title from the ContentDocumentLink to a text variable. In that context I am able to span through the relationship (ContentDocumentLink > ContentDocument > Title) and get to the title of the file. In fact, I replaced the pink element from the version above with an Assignment that sets three fields on a record variable: the ContentDocument Id (the Id of the actual file ), the Title, and the Created Date. (If two files have similar names, this might help the user delete the right one.) All the fields I need to show in my datatable on the next screen are now waiting for me. Here's the entire flow: In words it: Gets ContentDocumentLinks related to the record. Loops over them assigning variables. Adds those variables to a collection. Has a screen with a datable to select one ( only one ). Follows up with an "Are You Sure?" screen. Then deletes the selected file. Reduce, Re-use, Recycle ♻️ I realized after building it that this flow is actually 100% object agnostic . Though at the moment I'm only planning to put it on an onboarding page, the flow itself does not care what page(s) it might be put on. It accepts (actually requires ) a record Id as input. But that's just a text string. Using that Id, the flow loops over ContentDocumentLinks and finds information about the related ContentDocuments. The same screen flow can run from any object, passing in its Id, and the Get Records (screenshot above) will work without any modification. I can use this in other places within For Pete's Sake's Salesforce or even deploy it to other client orgs and use it there exactly as built. That's pretty cool and pretty rare, in my experience. Try This At Home! This is a pretty handy little flow and something you should be able to build for yourself using just this blog post. So go try it and let me know what you find! Your Org Might Be Different But before I send you off to your Flow Canvas, I want to make explicit a few of the considerations and tradeoffs in the way I have built this. You might want or need to make different choices. System Context, No Sharing I noted, above, that Erik Lopez suggested I could assign a permission set with Modify All Data, allow the user to delete the file, and then revoke the permission set. But you see that I didn't do that. Instead, I have the flow running in "System Context Without Sharing—Access All Data" a setting available in the Advanced Settings when you save a flow. This made for a simpler flow that was easier to build—I didn't need to find and assign a permission set, then revoke it at the end. Your comfort with this setup may vary. Deletes the File (ContentDocument) Directly As noted in the warning on the selection screen, my flow deletes the File (the ContentDocument), which cascade-deletes any ContentDocumentLinks sharing it to records. I could have built the flow to un-share to the record (delete the ContentDocumentLink to the record). But in For Pete's Sake's use case we are confident that the files are only attached to one record. So if we were to un-share, then the file would just be orphaned and taking up server space for no reason. I'm confident that deleting the file is the right action to take. In theory there could be a share to another record. Certainly in your org there could be shares to other records. In that case, you might need or want to delete just the ContentDocumentLink. But then you have the possibility of orphaned files that you might want to deal with. I can think of a few suggestions: Add a notification to the sysadmin that there is a file no longer shared to this record. (Note: The admin is going to have a challenge to find files with no ContentDocumentLinks. It's possible in SOQL, I think, but...) Delete the ContentDocumentLinks, leave the file orphaned, create some kind of cleanup via a scheduled flow that looks files with no ContentDocumentLinks. Again, I think this is possible, but it could have unexpected challenges. Have the screen flow check if there are other links to the file, only deleing the file if there are none. But if there are additional ContentDocumentLinks and your user is deleting this file because it needs to be updated, then you have other issues. Versioning This is a perfect segue to come back to the idea of versioning. As noted above, the Content Whatever pile of objects includes ContentVersion, which exists so that it's possible to save multiple versions of files in Salesforce. In the For Pete's Sake use case, for example, it might be that the "right" solution would be to actually update the file version , rather than deleting and re-uploading. But figuring out how to do that would be even more complicated. I decided not to even consider that path. I'd love to hear if you've ever used versions. Does Anyone Use This? As noted, I'm not sure how many orgs use versions. In addition, my gut says there are very few orgs that actually take advantage of the ability to share files to multiple records in the first place. It's an interesting idea and technical setup and I can see why Salesforce wanted to build Files that way, but it seems cumbersome to use, at best. Let me know if you think I'm wrong!
- Thing I Learned: NPSP Contact Role Triggers
Did you know that the NPSP triggers that automate opportunity contact roles (OCRs) are essentially built on the assumption that nobody will ever manually update opportunity contact roles ? I didn't know it. I knew that people would rarely do so. But I've always showed them that it could be done and left the buttons on the page to do so. I think this is a reasonable assumption, honestly, but it's a pretty big one that has some major implications, so I'm very surprised we (the nonprofit Salesforce practitioner community) have basically never talked about it. I feel like this should be one of those things we all point out regularly so that it doesn't slip through the cracks! What They Do The NPSP triggers exist to automate creation of opportunity contact roles for donors, matched donors, honorees, household members, people affiliated to the organization giving a donation, or people with a relationship to the giver. In the most concrete terms, the triggers create opportunity contact roles for the people that are in several NPSP fields: Primary Contact (on Opportunity, fieldname npsp__Primary_Contact__c) - This one's pretty easy to understand. Whoever is in the Primary Contact field will get an opportunity contact role and that role will be the one designated as Primary. Honoree Contact (on Opportunity, fieldname npsp__Honoree_Contact__c) - Whoever is in this field will get an OCR as the Honoree. [Actually, they'll get whatever role is set in NPSP Settings>Donations>Contact Roles>Honoree Opportunity Contact Role.] Notification Recipient Contact (on Opportunity, fieldname npsp__Notification_Recipient_Contact__c) - Gets the OCR set in NPSP Settings>Donations>Contact Roles>Notification Recipient Opp Contact Role. If there is an opportunity that is set up as a matched donation, then the primary contact of the matched donation gets an OCR set in NPSP Settings>Donations>Contact Roles>Matched Donor Role. And the triggers also create OCRs for people based on a few bits of logic: Household Members - Based on the settings in NPSP Settings>Donations>Contact Roles>Household Opportunity Contact Roles, members of the household that gave the donation all get OCRs. If a contact has an affiliation to the account that made a donation, then if there is a value in the Related Opportunity Contact Role field (on Affiliation, fieldname npsp__Related_Opportunity_Contact_Role__c) they will get an OCR of that role. If a contact has a relationship to the primary contact of a donation and there's a value in Related Opportunity Contact Role (on Relationship, field name npsp__Related_Opportunity_Contact_Role__c), NPSP will create an OCR of that role for the related contact. As long as you are just using those lookup fields and settings to manage opportunity contact roles, all is right with the world. The NPSP triggers will ensure that your donations will all have the OCRs as I laid them out. They're even smart and will only give any given contact a single role, based on logic for what takes priority . So far, so good. How They Do It It's how the NPSP triggers actually manage those OCRs that surprised me. Essentially, the triggers wipe out and re-create all the OCRs whenever there is a change to a donation that would warrant a new look at who should have contact roles. At first glance, you might think, "That's lazy programming. They ought to loop over the OCRs and only touch the ones they need to modify." But until the Spring '20 release Opportunity Contact Role was not a first class object, which meant there were limitations of what automations could do with them. When NPSP was being developed, therefore, the developers had to come up with workarounds. One was this compromise that NPSP wipes and re-creates all the OCRs, rather than looking at the OCRs that already exist and evaluating whether they need deletion or modification. The [rarely stated] corollary to this compromise is that NPSP assumes that nobody ever manually creates OCRs because any OCRs that have been added to an opportunity, or auto-created ones that have been modified in some way (such as to change a role), will get wiped out if there is a change that otherwise necessitates NPSP to evaluate and create OCRs. NPSP actually does have provision for organizations that want to manually add and modify OCRs. There is a checkbox on Opportunity called Disable Contact Role Automation (npsp__DisableContactRoleAutomation__c). Its help text states, "When selected, this field disables several aspects of NPSP Opportunity Contact Role automation, potentially resulting in incorrect or duplicate data. Refer to the product documentation for more details." In plain English: When you check that box on an opportunity, no OCRs will be auto-created for that opp. None. There is no in-between. If you check that box on an opportunity, even the Primary Contact will not get a contact role. If you leave it unchecked, any contact role you create using the New button, or any modification you make, is in danger of being wiped out. How We Noticed This I have a client, Modern Classrooms Project , that gets money both through fundraising and earned revenue, primarily the latter. For their earned revenue they're basically using standard Sales Cloud functionality. But on those earned revenue opportunities they use the Primary Contact field. (It's a super-handy way to immediately see who you should talk with about an opp.) When you put someone in that lookup NPSP gives them an OCR, marked Primary. Meanwhile, the sales team also adds other opportunity contact roles to the deal, keeping track of other people involved. But since contract negotiations can take time, sometimes the primary contact will change, of course. We recently realized that if you change the primary contact on the opp, the NPSP triggers wipe out all those other OCRs that the sales team has curated. Oops! An Easy Fix? Clearly, it's not that big of a deal for us to fix this. We just have to ensure (thorugh a Before Save flow) that all earned revenue opportunities check Disable Contact Role Automation . That ends the danger of losing data. If we wanted, we could leave donation opportunities to still have the NPSP OCR triggers, but we should probably, in that case, remove users' ability to make any manual OCR edits on the page. But we also have to deal with the fact that the automation around who is in the Primary Contact lookup is now disabled. Again, this isn't a huge deal, but it's not nothing either. I see two choices: 1. Build a flow to replicate NPSP's automation around Primary Contact . 2. Teach our users that there is no contact role automation, they have to create roles for everyone. (We'll probably go with the first option, since it's a lot more convenient for the users.) Implications for Your Org? Lastly, let me leave you with a "call to action": Consider your organization's use of the NPSP contact role triggers. If you have a hybrid situation, like I just described for Modern Classrooms, then you may have some work to do. If, as I think is the case for most NPSP orgs, you just want the out-of-the-box NPSP contact role functionality, then make sure that your users can't manually manage OCRs. Take the New button off the opportunity contact roles related list. And probably also Edit, while you're at it.
- Pick Your Partner With Care
I threw some shade on Salesforce last post for overselling and suggested that you should go to a partner first to protect yourself. Immediately a couple of people reached out to note that some partners aren't exactly paragons of virtue either, when it comes to selling both Salesforce and their own services. I got some eye-opening examples of not just subtle influence of the financial incentives but, frankly, unethical ways that partners have acted against their client's interests. So let me be clear here: Everything about Salesforce is a caveat emptor situation. (That's Latin for "Buyer, beware.") [Actually, everything about everything is a caveat emptor situation.] No organization should be making the decision to adopt Salesforce—or any other system—without a great deal of skepticism and as much trusted advice as possible from advisors that don't have conflicts of interest. And there are plenty of partners that have conflicts of interest. Question Me Depending on how you define it, I might have a conflict of interest. So don't just take my advice and my writings at face value, question me, verify what I say, get second and third and more opinions. I have noted previously that I am registered as a Salesforce partner. The partner program is very-much-not designed for independent consultants, nor even for small partnerships. I don't get deals from Salesforce, nor do I register my deals/clients with them. But I am enrolled in the program and get some minor benefits from it. Plus, of course, I'm a member of the Salesforce community and a Salesforce MVP . That means that I regularly receive swag, sometimes meals, occasional gift cards, and other benefits. I'm human, so surely these things influence me to some extent. You have to decide how much. But my intent—or maybe I should say my pledge—is always to put my clients and their interests first. I take this very seriously; I consider myself to have a fiduciary responsibility to my clients. I would hope all consultants feel this way. So there's my disclosure. Ask for similar disclosure from any partner you might work with. The Bigger They Are I cant get data on this, but I'm going to assert that the larger the consultancy, the more they rely on Salesforce for their book of business. It's just the way of the world that the larger deals are going to show up on Salesforce's radar first (The company is an absolute sales machine! ) and then those deals will go to the companies that are large enough to execute on them. It then becomes a self-reinforcing cycle as those companies rely more and more on Salesforce to find them large deals. And that doesn't even bring in the idea of "co-selling," which Salesforce encourages its higher tier partners to engage in. In a co-selling situation there really isn't a difference in financial incentives between Salesforce and the partner. I don't know what the actual financial entanglement is for a co-selling deal, but there's no doubt that a partner that co-sells is a partner that inherits the misplaced financial incentives that apply to Salesforce ( see last post .) I'm not going to name actual consultancies that act poorly (though people have given me insider insights about some specific companies). It's just my working assumption, at this point, that the larger the consulting company the more the troubling financial incentives can drive behavior. Could it happen at a small firm or even from an independent? It certainly could. I'm also not asserting that all consultancies do this nor, of course, that it's the case in all deals. I'm asserting that you should assume you need to take steps to protect yourself from being taken advantage of. If you're reading this as an employee of a nonprofit, whether already on Salesforce or considering adoption, your main protections are information (like this blog!), competitive bids, asking questions, and a healthy dose of " Trust, but verify . " regarding any advisor/partner/consultant. If you're reading this as a consultant thinking about the needs of your clients, I will argue that putting the client's needs ahead of your company or your personal interests is your job . Co-Selling: Ick! Bad for Customers "Co-selling" basically means that partners become subcontractors to Salesforce's salespeople. And they act like it. Here's an illustration: On the same day that I posted Don't Go To Salesforce First , I joined the monthly nonprofit partner office hours call. I don't find these calls particularly helpful, but once in a while I learn something that can help my clients. And it's a way for me to stay up-to-date with product roadmaps and developments in the nonprofit Salesforce space. That day I was five minutes late, so it took me a moment to catch up to the context. A fter about ten minutes it became pretty clear that the goal of that day's session was to communicate to partners what Salesforce's sales goals are for NPC in the next year because they are expecting partners to help achieve those goals . While I can understand why Salesforce wants partners to help them achieve these goals, I don't really think that's the partners' job. Their job is to advise their clients, to implement Salesforce, and to help their clients be successful on the platform. But apparently I misunderstand. Salesforce and at least some partners view it as the partners' job to sell the platform . That, in my opinion, is a conflict of interest. Because if it's your job to sell the platform, that means that at least in edge cases, you're going to sell it even when another option would be a more appropriate choice. Finally, let me leave you with some examples how co-selling means that partners hurt their clients. I heard that it's common practice, even company policy, at some Salesforce consultancies to: Suppress mention of the P10 Grant. — That's right, the consultancy actually told their people not to let clients know that they could apply for ten free licenses under the Power of Us program! I don't know if the co-selling partner is actually paid a commission based on license sales, or if they just get more in a particular account executive's good graces for ensuring a higher contract cost, or if there is some incentive if a client buys licenses when they could have had them for free. But not getting the P10 grant means the organization will pay a minimum of $4,950/year in license costs in perpetuity. Recommend Unlimited Edition. — Most organizations will never actually need the features that come with Unlimited Edition. Even those that will eventually might not have the need at the beginning of the project or for several years into their implementation. But by getting an organization onto UE from the get-go they have ensured a higher contract value and no P10 grant. (I will continue to point out that you do not need Unlimited Edition and that UE means no donated licenses .) Recommend Industry Solutions (including Nonprofit Cloud) even if it's not a good fit. — I've written plenty about my opinion of NPC and that it's not appropriate for small and medium nonprofits. I know that there are partners selling it to clients of those sizes, even if they know it will result in both short- and long-term pain (and cost). Include all license count up-front. — I've written about this problem before, including in my last post. System implementation can take a while. Larger projects for large organizations could take over a year. During that time you are not going to be using all the licenses you expect to use once the system is live. So paying for all the licenses you're going to eventually need is just wasted money before the system is ready. Follow the Money It's not hard to know who you can trust, just take a moment to understand their situation. If they're reliant on Salesforce for their livelihood or the survival of their company, then take that into account when they give you advice about system design and the costs that might entail. Independent consultants are working only for you. (And we're too small for Salesforce to care about as "partners" anyway.) Smaller and mid-sized consultancies are also only working on their clients' behalf. They rely on organization-to-organization referrals and their own hustle to keep everyone employed. The larger consultancies have great people working for them and do amazing work. (Plus, of course, only the larger firms have the capacity to take on large clients and their complex needs.) But the structure of their income streams mean the salespeople, in particular, might not have their incentives in the right place.
- Give Lively Can Use Free API Integration User
It's almost two years now since Salesforce gave us all a gift by allowing five free API-access only integration users (and more cheap) , which contains costs and improves security and audit-ability. But there are plenty of vendors out there that haven't gotten around to updating their packages to explicitly support this. Give Lively , one of my top recommendations to clients, is one of those vendors. But supported or not, you definitely can use free integration users for Give Lively and save some money. You just have to figure it out for yourself. (Or just follow the instructions I'm going to give below.) Meet Give Lively Give Lively is a donation processing platform that's free. (Like a beer, not like a puppy!) That means you can set up your account and start taking donations without any contract cost. Give Lively charges processing fees that vary depending on the transaction type. (Those fees are imposed by the transaction processing networks.) But Give Lively itself is funded by philanthropy and does not charge any fees of its own, nor do they charge for integration to Salesforce. Donors have the opportunity to cover the transaction fees, transparently offered as an option on the Give Lively form. And forms can also ask donors to give an additional gift to Give Lively at the time of donation. As I recall, these are also options you can turn off for your forms. And, perhaps most importantly for you, it's very easy to set up a new Give Lively account and get it connected so that donation data flows to your Salesforce instance. But their documentation indicates that "The Give Lively integration does not currently support the new Salesforce Integration user license type. At this time we recommend utilizing a standard Salesforce user license." Let's Try It Anyway At some point I either hadn't read that, or it wasn't in the documentation yet, or I just decided to ignore it. I think probably I was excited to save a client a paid license and just went about trying it out before Give Lively had even assimilated that Salesforce had released the free users. So I don't think there was documentation saying it couldn't be done, I just had to figure out what to do. There are plenty of examples of apps out there that insist that to work with their tool you need a system administrator profile. Some dip their toe in good security practice and say you don't need a sysadmin profile but that you need permissions to view any object or field and change any setting in the app. While I'll concede this might be required for certain bits of functionality in some apps, it has to be rare. Saying "you need to be a sysadmin" is just being lazy. If you tell people they can only use your app as a sysadmin then you don't have to put as much thought into what missing permissions could get in the way. Give Lively's integration is a good example of this. At its heart, if you think about it, the Give Lively integration just needs to be able to insert an opportunity, contact, and/or campaign. That's eminently possible for non-admin users. ( Please assure me that your fundraising users are not on a sysadmin profile! ) When you log into the back end of Give Lively and work with the Salesforce integration setup, you can see that they've built a tool that will automatically apply permission sets to the sync user. The ability to actually do that requires an admin-type permission. But first of all, that tool is kinda' optional. We could manually grant permission sets. And anyway, you can grant the permissions that tool needs without granting all the other permissions of sysadmin. So at some point Give Lively saying they don't support free integration users is just them being unwilling to work on updating their package. I get it—we're all busy and bandwidth and funds are limited—but if you don't want to change the package, you could still change the documentation. I know there are other integrations out there that require a sysadmin profile because the integration actually checks that the profile of the integration user is System Administrator. (I'm looking side-eye at you, Classy .) That's truly lazy, as I'm sure the user could work with individually granted permissions. But they've hard-coded a profile name and they're not bothering to fix that. I would say that's unconscionable, particularly from a company that is charging a hefty fee to use their platform and an additional fee for the Salesforce integration. (Again, looking hard at you, Classy.) Spoiler Alert: Not Even That Hard So if we ignore Give Lively saying we can't use a free API integration user we just have to figure out the right permissions to grant that user and this is going to work. Fortunately the Give Lively app isn't hard coded to look for a full Salesforce license. (I'm pretty sure you could not have Give Lively log in as a Platform User license because those can't be granted access to Campaigns.) Step 1: Build a Custom Permission Set The Give Lively package installation (which I'm already assuming you've installed) comes with a couple of permission sets for granting users access to the fields from Give Lively. One is called "Give Lively Integration User" and is meant to be granted to an integration user. But since that one is limited to the license type Salesforce (a full license) instead of having nothing in that field, it won't be available to a free API user. So we're going to have to make our own permission set. At the top of Give Lively's documentation they list the permissions you need to include in this set. Make your new permission set. My name and description are only suggestions: Name : Give Lively Integration Perms Description : Additional permissions required for the GL integration user according to documentation at https://www.givelively.org/resources/salesforce-integration-set-up Allows GL to use a free integration user profile despite what their documentation says. And include the following things within this permission set: Permission Set Overview> Object Settings> Contacts Grant access to any record types used in your org. View All and Modify All Edit access to the field give_lively__User_ID__c Permission Set Overview> Object Settings> Campaigns Grant access to any record types used in your org. View All and Modify All Edit access on all of the fields from the Give Lively package. I count six fields: give_lively__Event_End_Date_Time__c give_lively__Event_Start_Date_Time__c give_lively__Campaign_Id__c give_lively__Campaign_URL__c give_lively__Event_Id__c give_lively__Text_Code__c Permission Set Overview> Object Settings> Opportunities Grant access to any record types used in your org. View All and Modify All Edit access on all of the fields from the Give Lively package. I count 17 fields: give_lively__Anonymous_to_Public__c give_lively__Campaign_Id__c give_lively__Client_Application_Name__c give_lively__Donation_Id__c give_lively__Event_Id__c give_lively__Subscription_Id__c give_lively__Net_Amount__c give_lively__Page_Slug__c give_lively__Page_Type__c give_lively__Page_Url__c give_lively__Payment_Platform_Transaction_Fee__c give_lively__Referrer_Url__c give_lively__Text_Code_Used__c give_lively__Transaction_Fee_Covered_By_Donor__c give_lively__Utm_Source__c give_lively__Widget_Type__c give_lively__Widget_Url__c Permission Set Overview> Object Settings> Accounts View All and Modify All Permission Set Overview>System Permissions View All Data Modify All Data API Enabled Assign Permission Sets Download AppExchange Packages Manage Profiles and Permission Sets Password Never Expires Note: On the objects View All and Modify All may be overkill. And View All Data and Modify All data overall may also be overkill. I have not experimented. But based on Give Lively's instructions, I granted those to see if I could get it to work. (Since they kinda' expect that you'll use a full system administrator, I figured this wasn't much different.) Step 2: Create the User, First as a Full User Next you are going to create a user for your Give Lively to log in as, something like First Name : Give Lively Last Name : Integration Set the email to somewhere you are going to be able to get the password creation message, though possibly not your email directly, it can be a group mailbox. Give the user a full Salesforce license and, for the sake of simplicity right now, a System Administrator profile. [This is not required. You could create this user directly as an API Only if you wanted. I tend to create integrations as user as a full user first. By creating a full user it's nice and easy to ensure that I am able to log in as that user and that it has the permissions I expect. Then I change the user license, profile, and permission sets after I've got it set.] Make sure you set Marketing User = TRUE. Step 3: Set Up the New User Password Get the password creation email and log in as Give Lively Integration. Make sure you know the password. (Consider saving it in a password manager or secure place your colleagues could access it, if needed in the future.) Step 4: Log Out of Salesforce Now make sure that you are fully logged out of Salesforce. If you are still logged in with a cookie, then the next step when you work in the back end of Give Lively may immediately log in as real you, not Give Lively Integration. Step 5: Connect Give Lively To Salesforce Log in to your Give Lively account and get to the place for setting up the integration. [According to this page , " click the 'Get Integrated' button and proceed through prompts."] When you log in, use the Give Lively Integration User —make sure not to log in as Real You! When the login is successful you'll see buttons for applying the Give Lively permission sets to the user. Go ahead and do this. You'll also see a Sync Now button. Might as well test that! In the Advanced Settings tab you can make choices about how you want Give Lively to deal with the data that goes to Salesforce. In particular, this is where you set the record type of opportunities it will create (you don't want it to just use the default record type for the profile it's logged in to—that might not be the right one) and the campaign (if any) that it will put those opportunities on. Step 6: See The Data Flow to Salesforce I now put a real donation into Give Lively to make sure that the data is flowing. If you're still testing Give Lively in your sandbox, they give you a fake credit card number you can use. But when testing the final setup I just make a donation of a few bucks to my client. Then I know it's really working in a real setting. Log back into Salesforce as Real You. Then look for the contact that the donation was made under. You should see the opportunity in their related list. Check that everything looks right. In particular, check that the opportunity was created by the Give Lively Integration user. Depending on your Give Lively settings, it might take a few minutes for the opportunity to sync. You can also speed things up with the Sync Now button in Give Lively. Step 7: Modify the Salesforce User If you've never created an API-only integration user before, you can use my instructions . But assuming you're in a position to set up one of those users, we're going to just modify the user we created in step 2. Edit the user: Switch the User License to Salesforce Integration . When you make this switch you'll get a pop-up warning you that any assigned permission sets or permission set groups will be unassigned. That's OK. We're going to set things back right in a moment. Set the profile to Minimum Access - API Only Integrations . [You could use Salesforce API Only Integrations if it shows up in your org. I don't think there's a functional difference.] [Update 4/2025 - I have gotten at least one report that this works with Salesforce API Only System Integrations but not with Minimum Access - API Only Integrations. I definitely used Minimum Access, as originally written. But do what it takes for you to get it to work!] Make sure you leave Marketing User checked. Now we've got a user that has access to basically nothing. So we have to assign permissions. Grant this user the Permission Set License Salesforce API Integration . (This is a step you always need to do for an API integration license user, it's not specific to Give Lively.) Now assign permission sets that grant access to the objects and fields the user will need. In this case, what really matters is your permission set Give Lively Integration Perms that was created in Step 1 . But for convenience you can grant the other standard permission sets for users in your org. And for safety's sake, I've been granting Give Lively Additional Permissions that is installed by GiveLively. (Though I found out the hard way that this alone isn't enough for the integration to work, which is why we built our custom one.) Step 8: Test Again in the Back End of Give Lively Now that you've modified the user, I recommend going into the back end of Give Lively and confirming that it still validates. Note that the Apply Permission Sets button will not work for the integration user. This is OK, just ignore the red error. Step 9: Send a Donation Through I don't consider it fully reliable until I've put a real donation through using a real credit card. Within the sync timing, it should show up in Salesforce. Yay! That's All! By following this relatively simple set of instructions you've just integrated Give Lively to Salesforce using a free API Only integration user instead of a full user license. Give yourself a gold star! 🌟 You've just saved your organization $500/year!
- Don't Go to Salesforce First!
If you're thinking of purchasing/adopting/implementing Salesforce [the platform], don't start by talking to Salesforce [the company]! [Timingwise the true target audience for this blog isn't likely to read it in time. But I have to try to get the message out any way I can. Please share widely!] As a platform that your organization might use, Salesforce is a competitive choice. It might not be the only one, or necessarily the best for your situation, so do your due diligence . But if you have considered the options and are ready to actually adopt the system, this is a perilous time: You know you want Salesforce, but you probably don't have the background or expertise to know what you actually need. Salesforce is a big platform with all sorts of related products, not to mention complicated pricing just for the base licensing . So make sure you get appropriate unbiased advice. Incentives Are Against You You know who won't give you unbiased advice? The company that will benefit most if you over-buy. There is no way around this, the incentives are clear (and companies and people respond to incentives). Salesforce is incentivized to sell you more than you need because that is free money for the company. Salespeople (account executives, or "AEs") work on commission, so they have a clear incentive to sell you more sooner . And they know all the tricks. They'll give you a discount if you sign a longer-term contract. (Which locks you in to an over-buy for longer.) They'll cut a better deal if you sign before the end of a fiscal quarter. (Which often means you're buying products before you're ready to use them.) They'll throw in "extras" like Premier Support. (When the contract renews, you might not consider the feature worth the cost. But will you remember to take it off before the renewal is signed?) Don't Let This Happen to You There's one really clear example that I've heard many times. (As in: Multiple consultants have told me that they've seen this situation happen personally. I've heard it from enough people working for different partners to be proof that it happens rather often.) A medium-sized nonprofit contacts Salesforce because they're thinking of adopting the platform. Perhaps an executive thought, based on Salesforce's aggressive marketing of the Power of Us program , that by virtue of being a nonprofit they would get the best, most honest deal by talking directly to the company. Sales contacts them, hears that it's a good-sized potential contract, and immediately sees dollar signs. The pre-Sales team does an impressive song and dance with lots of people on the calls, including employees that talk about how they used to work at a nonprofit, highly technical solution engineers, and maybe even a solution architect. Of course Salesforce shows one or more whiz-bang demos. They scope out a great "digital transformation" that's going to yank this nonrprofit straight into the 23rd Century. And they even manage to put a price estimate on it that sounds reasonable (and is, coincidentally, just within the stated budget of the nonprofit). Then they get the nonprofit to sign on the dotted line. Based on the discussions, Salesforce has estimated that implementation will take six to twelve months. And the project calls for all—let's say: 75—of the organization's employees to be on Salesforce once the digital transformation is complete. With the contract signed and payment in hand, Salesforce suggests one or more "SI Partners," system implementers, that the nonprofit should work with. The organization does some negotiating over hours, contract language, etc and eventually picks a consultancy (a "partner" or "an SI"). By the time the contract with the consultant is actually signed, it's probably been a month since the contract closed with Salesforce. Then the real work of the implementation begins. Let's assume it goes incredibly smoothly and is actully complete in six months. Sounds great, right? But what I hear from partners that are involved in that deal is that their client has already been ripped off . Salesforce started charging for 65 licenses on the day the Salesforce contract was signed. The first ten were free, under the Power of Us. The digital transformation plan called for 75 employees that will eventually use the system. Salesforce put the full license count in the original contract, even though they knew most would sit idle for months or even a full year. The implementation is going to take at least six months. During that period of time only a handful of licenses are needed: those for the implementation consultants and the few employees liaising with the consultant. The organization doesn't need all 75 licenses until they actually get all 75 employees onto the system and train them how to use it. Building and testing can happen within the ten free licenses. So in my rosy scenario, where implementation started after just one month to select a partner and then completed at the bottom end of the estimated time (6 months), the nonprofit has effectively wasted at least [65 licenses X $41.25/month x 7 months =] $18,768.75 . If their contract includes any other products (Marketing Cloud, Premier Support, a Full Copy Sandbox, ...) the waste just grows. And the partner knew this from the moment they started bidding on the project. But it was already too late. The contract with Salesforce was already signed. If that partner didn't take the deal, another would. And what partners tell me all the time is that they're not sure what kind of messaging is even useful in this case. If they point out to the nonprofit (AKA: their brand new client) that they were taken advantage of, it's not going to claw back the money. And if Salesforce finds out that they mentioned it, they [rightly] fear they'll be punished. So sometimes they just don't mention it. Sometimes, if there's a quiet off-the-record moment, they let the organization know. Hopefully they coach their client before renewal rolls around to make sure that they're only renewing for licenses and products they're actually going to use. But even that service to their client isn't guaranteed. It depends if they're still working together when renewal rolls around. And they still face the fear that Salesforce will find out they tipped off the organization. So talk to an implementation partner early! Actually, talk to more than one. And don't give much credence to one that Salesforce has matched you up with. Besides the clear risk I just detailed, the incentives get skewed in all sorts of ways when Salesforce makes the referral to the partner. I've heard from multiple people at multiple consultancies that if they're talking to an organization that was sent to them by Salesforce, they feel like they can't speak honestly about which products the client might use, for fear that Salesforce won't give them the next deal. To be clear, the consultants taht are telling me this do try to find a time to let their client or potential client know the score, but only on a non-recorded phone call, when there are no Salesforce employees around, and otherwise with a, "You didn't hear this from me, but...." kind of framing. In other words, to give honest advice, they have to be circumspect about it at best. That tells you all you probably need to know. Implementation partners can have wrong incentives too, of course: to sell you more time and a bigger project. But you have a way to mitigate that: you can get multiple quotes. Plus a partner has a longer term incentive to keep you happy so you will refer them and come back to them for future projects. For the platform company, Salesforce, there really is no comparable mitigating factor. Sure, if you get really pissed, you might migrate off Salesforce and cease being a customer. But there are barriers to that. (Migration and re-implementation are never fun, always costly, and usually stressful.) So in most cases, if you over buy, you're just going to eventually fix the contract but not leave the system. Thus Salesforce doesn't even face consequences. Your Mission, Should You Choose to Accept It The bottom line: you need to find an implementation partner that you can trust. If you have already let Salesforce know that you're considering the platform (or additional products of theirs), they're going to start the sales pitch and connect you with a partner they think you should work with. I have no problem with most of the partners they might recommend—they're mostly the same people you would find on your own. But there's a pretty huge difference in incentives if you've come to the partner on your own than if Salesforce made the referral. Find a partner (or two, or three) on your own. Have a few conversations. Get the vibe. Find a main contact that you can trust and an organization whose work style is going to be a good fit. Salesforce need not know anything about your plans until well into your conversations with partners. In fact, I think you should go pretty far down the path—probably all the way to signing a scope of work with a partner—before you ever contact Salesforce to start getting your org and your licenses. That way the partner can advise you on how to save money for the long term. They can help you avoid overbuying. They can advise you on how and when to negotiate with Salesforce for the things you do need, and when to choose products that come from other vendors.
- You Don't Need Docusign (or Adobe Sign, or ....)
Every so often a client says "we need to add Docusign to our online forms." Usually it's really, "Our lawyer told us we need to get signatures from our participants." I'm the son of a lawyer, so I'm totally on board with having clear documents and contracts signed by both sides. But we've been living in the new millenium for a quarter century now, "getting signatures" doesn't literally mean putting pen to paper. I don't start a project until I have a literal contract signed and countersigned. But there are no pens nor paper involved. Fortunately, to date I've never actually touched the Docusign platform, nor Adobe Sign, nor any of the other competitor offerings. Naturally I've signed things using Docusign, when someone else sent one to me. But I haven't yet found a case where I or one of my clients needed to be on the paying end of that deal. It's a relatively rare circumstance to need to pay for an e-signature solution. Save your money. We're all about saving money on this blog, so let's talk about ways you and/or your nonprofit might "do Docusign" without actually paying for it. Because those services are not cheap! The last time I checked, there was both a substantial monthly fee and then a cost per "envelope" you send out for signature using Docusign. I'm sure the competitors figure out their pricing in myriad other ways. But I have no interest in considering whether one service is less expensive than another. I always start with, "Can we do this for free?" What is actually necessary? Get your lawyer and your boss to agree. My first step, every time a client brings it up, is to push back. Most nonprofits don't have a full-time lawyer on staff. They've usually got pro-bono help that's episodic, at best. So when someone comes to me with the requirement that they "get electronic signatures," the first thing I do is ask what that means and where the mandate came from. If it was the organization's attorney that mentioned it, we're going to need her to get a lot more specific. If it was leadership in the org that just realized they want to cover their butts, then let's figure out what kind of butt-coverage is modest enough. It's my understanding, from talking to attorney family and friends, that there are plenty of non-signature options that can be considered legally binding. Pen-on-paper (a so-called "wet signature") is not the only option. Included among the options is filling out an online form that says something like "by entering my name into this box I agree that this is like my electronic signature." We all know there's plenty of precedent for companies including legal requirements that one tacitly accepts just by clicking a checkbox or even as little as continuing to work with the company. This isn't a legal blog, so I'm not going to go further into this. My point is that in 2025 there are many ways to "sign things" that don't involve any particular technology or service. Of course, I am not a lawyer. (I don't even play one on TV.) So I can't give you legal advice. Even lawyers give advice only, they rarely have a definitive answer, only their best advice given the history of court decisions, history, etc. Famously, two lawyers also may disagree on even the simplest question. So in the end, you have to figure out what advice your orgnization is going to put into place as policy. This is why the first thing I do is push back to get clarification. Whoever said you "need signatures" should be asked what is an acceptable proxy, since they almost certainly do not mean a wet signature. This is ultimately the decision of the organization leadership, in communication with the organization's legal counsel. So make sure leadership understands that there are costs for tools and their implementation. In the end, they have to either "sign off" [pun intended] that the cost is worth it, or that an alternative (cheaper or free) solution is legally sufficient. Perhaps Any Webform Will Do If you have any tool for online forms, including Google Forms, then you already have one option for getting e-signatures totally free. As I noted above, taking action to fill in a form, such as adding your name, email, or the like, can be considered legally binding. So consider adding some legalese to the form that makes it official. Of course, make sure that your organization's legal counsel is comfortable with the wording. But this might be all you ever need to do. Most of my clients have gone this route. No extra work beyond getting the language written. Built-in Features If you're using something a little more sophisticated than [free] Google Forms, you might have some kind of e-sign capability already available to you. My go-to webform tool is FormAssembly , and they have an e-signature feature. If you're already paying for FormAssembly, you can decide to enable e-signature on one or more forms without paying any extra. Enabling this feature is going to give you a little more formality compared to what I outlined above. You'll want to put some time into understanding exactly how the feature works in your tool. FormAssembly's feature, for example, is pretty simple: The user enters an email address. When they click Submit, they are sent an email. They have to click a link in the email before the form is finally processed. (There is no "signature" box with a script version of your name.) Of course, this requires that the form user have access to email as part of the signing process. If you were hoping to use FormAssembly's e-sign on a tablet at the check-in for an event, you might not love how that works. From a technical point of view I think FormAssembly's version is about equally secure and verified as Docusign. But since it works differently from the platform people might be most familiar with, be sure to show your leadership and your lawyer the functionality. Tangent: A True "Wet Signature" Alternative ✍️ Since we're talking about signatures, I want to take a bit of a tangent to tell you about one of my favorite life hacks. This has nothing to do with Salesforce, but it's relevant to the day's discussion. Did you know that it's easy to add a "real signature" without going to the trouble of printing and scanning? If you work on a Mac this is an absolute slam dunk that has been available to you for decades: The native Preview app can save a signature and easily insert it into a PDF. I've been signing contracts, government forms, and the like using this tool for as long as I can remember. Even when a bank "requires" that I print, wet-sign, and scan, I manage to use this trick. I also use the Annotation feature of Preview to fill in other parts of PDF forms, not just the signature. (It's years since I looked for a similar method to this on Windows. At the time, I couldn't find anything convenient and free . Maybe things are better now? 🤷🏻) When I generate a proposal and contract, I save it as a PDF, insert my signature using Preview, and then email it off to the client. My side's all done. I just need the counter signature. (Clients accomplish their side in various ways, of course, depending on what tools they have available. If they ask me, I direct them to digitally inserting a signature.) Of course, I'm a solo consultant, so I'm not doing a lot of contracts. But if your organization has a very small number of cases in which you truly need (or want) something like a wet signature, you might consider whether marking up a PDF with Preview or a Windows equivalent would get the job done. Your solution could be "Free Like a Puppy" I just want to reiterate that your mileage may vary. Depending on your circumstances, a "free" solution might not really be free. A simple "By filling this box I agree to sign" section on a Google form may be plenty sufficient most of the time. But if you had to take someone to court, the evidence you present that they "signed" that form might not convince a judge or jury. (Not that a wet signature or a Docusign might be a slam dunk either.) Using the included e-sign feature of, say, FormAssembly, assumes that you're paying for FormAssembly every year in the first place. And don't forget that convincing your executive director or your legal counsel to accept one solution or the other will take up some of your time, even if you avoid adding an expensive e-sign platform to your tech stack...
- A State Processing Engine
This is my third post about platform events. Last time I shared a few things I've learned about this tool. Now I want to share some great advice I got from my friend Chris Pifer about how to work with platform events. The trick is to allow the platform event to break processing into individual asynchronous bites but not lose track of the state of the work. Use Case I'm working with CollegeSpring , who runs college preparation classes for schools all over the country. They need to bring in records from their learning management system (LMS), called Buzz. Once CollegeSpring sets up the LMS for the partner school, the students (and teachers) mainly are tracked in the LMS—that's the system of record for their names, school Ids, and which classes they're in. The LMS has thousands of records: students (contacts) are enrolled (junction object) in classes (custom object) that are connected to pro grams (custom object) that are related to schools (accounts). We can get a spreadsheet out of Buzz with a row for every student and teacher, indicating their enrollment. But when we get the spreadsheet again a day or a week later we want to figure out, in Salesforce, whether the student exists (create them if not) and their enrollment is already recorded (create it if not, update it if changed). Particularly at the beginning of the semester, students might come and go or move around from class to class. Simple in Theory Thought about singly, a row of the export from the LMS is quite simple: Student Name (and unique LMS Id) LMS Enrollment Id Enrollment Status Class LMS Id Program LMS Id (tied to school Account) A flow to check if the student, class, and/or program exists and then create or update as required isn't that hard to conceptualize. The problem is that this flow might hit limits when it runs, particularly if you're inserting a lot of records at a time, as we intend to do. So from the start I wanted to set this up so that processing would be asynchronous and would run for one record at a time in its own transaction. That's where platform events are my friend. Platform events also gave me the option of partially processing the import record as it goes through its steps. That has three benefits: If a later step fails the earlier parts that were successful don't get rolled back . In other words, I can save partially processed records in that partial state. Later, I can fix whatever caused them to fail, and then restart processing. When re-running the flow (ie. reprocessing the record) it doesn't have to redo work. In any given processing step I have just two or three SOQL or DML operations (pink flow elements). A Complicated Flow? The actual flow, once built, looks a lot more complicated than it really is. But that's because I've put in a bunch of fault paths and logging. I almost don't want to show you a screenshot for fear I make it seem scary. But here you go: Actually Not Complicated I promise you, here's all the flow is really doing (illustrated in LucidChart because flow isn't really built for screenshots): In words instead of image: A platform event is published, which kicks off the flow. The flow looks up the import holding object (called a BuzzDataUpload), where all the data about the import is living. (I didn't put data on the platform event, it all lives on the BuzzDataUpload.) A decision checks if all the related objects have already been found and their lookup fields filled. (It checks the state of the record.) If so, set the BuzzDataUpload's processing status as "✅ Complete" and we are done. If the Account lookup is empty (meaning the import object hasn't yet been matched to an account) do a Get Records to find the account, update the BuzzDataUpload record with the Id of that account and set its processing status to "⏳ Processing," publish a new platform event. (Go back to Start.) [If no account was found, update the import record with a processing status of "⛔️ Processing Error." Do not publish another platform event.] If the Account was filled but the Contact lookup is not filled, upsert a contact, update the BuzzDataUpload record with the Id of that contact, publish a new platform event. (Go back to Start.) If the Account and Contact lookups are filled, but not the Enrollment, upsert an enrollment, update the BuzzDataUpload record with the Id of that enrollment, publish a new platform event. (Go back to Start.) Etcetera until the BuzzDataUpload has been fully processed. All the Bells and Whistles My final flow has a lot more elements on the canvas in order to include a bunch of refinements, including things like: Counting the number of platform events that have fired, as a check on how many times the record has run through processing Inserting FlowLog records at various places to help with debugging Lookups for record types before creating records (like enrollments) Decision elements to check if the field(s) we are about to use to look for records are outside of expected values, such as the Role field Fault Paths on just about every Get Records or Create Records step to log if there is some kind of error A Processing Notes field that the flow updates when it has an error (like in step 4d, above) The real use case has five fields that eventually have to link the BuzzDataUpload to records of other objects, so two more full branches of the flow. But none of that changes the heart of the flow. It's simple in concept, but in reality covered in frills and decoration. What to do with ⛔️ Processing Error ? It might seem scary that I've got a branch of that flow that might mark a BuzzDataUpload with "⛔️ Processing Error." But that's the fun of the State Machine. With that field value we know that BuzzDataUpload needs reprocessing. (And the Processing Notes field tells us where processing ended.) That leaves just two things we need: A way to fix whatever problem happened the first time A way to send the record to be reprocessed Fixing the Problem Let's take the case of 4d in the example above. If there was no account found based on the values in the import holding object, we don't want to create an account. The account should definitely already exist in Salesforce! (It's one of our partner schools. We have an opportunity that's closed won, details of our contract, several people that are our main points of communication with the school. If we don't have those things, that seems bad...) The records we're importing from the learning management system include the LMS Id of the school as well as the account name. I want my flow to match on the unique Id, so there is no chance of confusion if school names are similar, mispelled, or whatever. But if we haven't entered the LMS's unique Id for the school into Salesforce, then that Get Records step is going to fail. I want that to happen! Now the flow just marks the import object as follows: Processing Status: ⛔️ Processing Error Processing Notes: "No Account found with LMS Id that matches this import record." When a human sees that processing note it's pretty obvious what needs fixing: We have not taken the LMS's program Id (created when the program was set up for the school) and associated it to the partner school's account record in Salesforce. [Hopefully we don't get to this point very often. We have an audit report to watch for partner schools that should have a program this year but don't. And we have another report for programs for this year that are active but don't have an LMS Id. But if neither of those audit reports caught the problem or if it wasn't fixed before we imported the LMS data, then the processing of the LMS data for each student and teacher at the school is going to error.] So once we see a record with the note "No Account found with LMS Id that matches this import record." we just have to add an LMS Id to the right account. Next time that record is processed, it shouldn't have any problem. Sending it to Reprocess Reprocessing a BuzzDataUpload record is as easy as checking a box. Whoever is working with the BuzzDataUpload record can check that box on a single record. Or they can use a list view to bulk inline edit the Reprocess box to checked. Or they could do it in even larger numbers at a time through Apsona . Once the box is checked, there's a record-triggered flow that publishes a platform event (and unchecks the box). Publication of that platform event kicks off the flow above. And we're back to the beginning, a very good place to start.. The State's the Thing Each time the platform event is published it causes that one BuzzDataUpload record's state to be checked, where the state is represented by all the lookup fields to the other records thats should exist when processing is complete. If one or more are not filled, the record needs another turn through the flow. If they're all filled, then we are done: The Single-Record Workaround Last post I mentioned that if platform events are published in batches they also get processed in batches, which can result in errors. I promised a workaround. (Credit to Andrew Russo for teaching me this one.) Originally I had a record-triggered flow that ran on any insert or update of a BuzzDataUpload record and published a platform event to kick off processing of that record. Since the inserts/updates were happening in bulk, processing was in bulk as well and I was finding weird errors. (Like my upsert of the contact erroring because there was already a contact with the unique LMS Id, which clearly was what the upsert was supposed to avoid!) Andrew's workaround was to put publishing of the platform event onto a scheduled path, where you can set the Batch Size to one . Adding a scheduled path to my flow also meant that I needed to have two flows, rather than just one. On Create On Update (when Reprocess is changed to be true.) (There's no way to combine those two flows because you can't make flow entry criteria that will pick up a new record and pick up a change to Reprocess "Only when a record is updated to meet the condition requirements," which is what you need in order to have a scheduled path.) But those flows are otherwise identical: On the immediate path, the BuzzDataUpload record is set to Processing Status "⏳ Processing" and Processing Note "Waiting to publish platform event." After the zero minute pause (which, in practice, seems to take at least one minute) the platform event is published (in a batch size of one). This does mean that insert or reprocessing of records waits for at least one minute. But the productivity gain over records erroring is worth way more than that!
- What I've Learned about Platform Events
Platform Events are a great tool to add to the admin's toolkit, but they take a moment to wrap your head around. And for those of us that are declarative-only, their strong scent of "developery-ness" adds to the wariness. But once you break them down, they can be pretty handy! Back in October 2023, six years after first encountering the idea of platform events (on Trailhead), I rediscovered them and then wrote about them . Since then I've learned some things, sometimes the hard way. Definition Before you go back and read that earlier post (which you should, but maybe after you finish this one !), here's the quick download on platform events: They're a tool "to connect business processes in Salesforce and external apps through the exchange of real-time event data." That second clause reminds us that platform events are generally used for integrations . But they don't have to be an integration to an external system, they can connect processes within Salesforce , which is what I'm interested in. Platform events can have fields, like records do. So you can use them to transmit information between the processes you're connecting. (More on that later.) But unlike records, platform events do not persist anywhere. They get "published" to any processes that are listening ("subscribed") and then they disappear, leaving little or no trace behind. Platform events go out more-or-less instantly from your process that publishes them. However, the publishing is technically asynchronous. Because platform event processing is asynchronous, any processes that are kicked off by a platform event are outside of the transaction that published the event, so those processes get their own set of Salesforce limits. Limitations and Learnings I hadn't picked up on all of those initially, so that's why I wanted to share with you. [This one actually isn't new to the discussion at all, but it's worth repeating:] Platform events do not persist. If you want to see that an event fired, you're going to have to take some measure of your own, like have a platform event-fired flow create a Chatter post, or a Task, or a log record. (I create log records using My FlowLog Object .) Otherwise, platform events are like something shouted: If you heard it, great. If not, the sound is gone. Platform event-triggered flows can't call subflows. I don't really know why not, but they can't. (Mostly this is a minor annoyance, since you could rebuild the functionality of what would have been the subflow within your PE-triggered flow.) I am told* that if you have a batch process that publishes platform events in a batch, flow will also process those events in a batch, not singly. (Which was how I understood it to work.) Apparently in a platform event-triggered Apex class you can set a batch size for processing. But in flow you cannot. So when I built a process that fired a platform event every time a record of my holding object was created and then bulk imported into that object (using Apsona ) I didn't realize that my platform event processing flow would take things in batches since the events were fired in batches. [There's a workaround that I'll write about in my next post.] That lead to errors and to me being very confused by those errors.. * Intentional passive voice there. I can't find documentation to point to. I certainly experienced this, so I believe it to be true. And while the person that explained this probably wouldn't mind if I mentioned them, I am going to let this be my own writing and take personal responsibility if I've gotten it wrong. You can build a platform event-triggered flow to run in system context (it runs as the Default Workflow User) or as the user that triggered the publishing of the platform event. But either way, as I understand the note here , "if a flow interview creates or updates records, system fields like CreatedById and LastModifiedById reference the user who published the event message." I found that both a little surprising but also quite useful. It means record creation/processing is less anonymous than it might otherwise have been. I am also told that it's possible (though extremely rare) for a platform event to be missed by the subscribing process. This, in combination with the fact that platform events don't persist anywhere, means that you probably want to avoid storing data on the platform event that wouldn't otherwise be reproducible. For example, I was recently working on a process by which a user will import thousands of records from an outside system. The records go onto a holding object that has, say ten fields. The holding object records are then processed by a flow into several related records, based on the values in those fields. (Similar to how the NPSP Data Importer works to take in a row of person, account, and donation data and turn that into contact, accounts, opportunities, and campaigns.) I asked some questions on MVP Office Hours and, at one point, someone suggested that perhaps instead of uploading into the holding object, I should just upload as platform events directly, with fields on the platform event for all the data, like I have on the holding object right now. I didn't even realize that it was possible to directly upload platform events (directly publish them)! But even if I had known that, a few things would worry me about that approach: If the platform event were missed, it would be like it had never happened and we would have no way to know. Even if this is a one in a billion case, it worries me. If the flow picks up the publishing of the event, but then errors, I would have no way to see the data that needs reprocessing or how far it got before failing. We would have to go back to the spreadsheet that was being uploaded and figure out which ones didn't process properly. That seems burdensome. It would be very challenging to build, test, and debug the processing of the platform event into the related records because I couldn't see what was going on. (Maybe that's just me. I need to see the process as it moves step-by-step.) Note also the distinction in platform events between Publish Immediately and Publish After Commit . It's a subtle difference that I'm not sure I entirely understand. But "immediately" means that your publishing action (such as a Create Records within a flow) always publishes, even if the flow proceeds to fail and roll back the transaction. That could mean that an event fired referencing a record that proceeded never to have existed. So make that choice carefully when defining the platform event or you could run into trouble later on. More to Come My next post is going to be a full description of what I recently built using platform events. Watch this space!
- "Why do you hate NPC?"
I bet some of you have been wondering why I hate new Nonprofit Cloud (NPC). I'm not sure anyone has ever asked me directly with exactly this wording of the question, but I've definitely had people ask me a question in the same genre. No doubt I've written pretty harshly about NPC, directly, in the Emperor's New Clouds , and less directly, in posts on extension objects , person accounts , and even Salesforce's business strategy . I tend to be pretty transparent about what I think. But I don't hate Nonprofit Cloud. I mostly don't care about it. I don't think it's a product/service/offering that is going to affect my business or the day-to-day operations of my clients, small nonprofits. A Car Analogy I'm reaching for a car analogy to make this clear: I have about as much interest in Nonprofit Cloud as I have in Maclarens. That is to say, very little. For my whole life, my family has owned relatively practical and affordable vehicles. Toyota Camrys, Honda Civics and Accords... Not the absolute cheapest on the market, for sure, but not much in the way of vehicular splurges. [Sure, there has been some fun in the mix. My first car was a sweet 1967 Olds 442 convertible that my uncle loaned me long-term. And I bought a Celica convertible in my twenties that I drove until taking my mom's hand-me-down beige 1998 Toyota Camry in 2006 to fit two kids. I drove that one until 2022 (and my children are still driving it). Two years ago I bought a Polestar 2 electric vehicle. That was pricey, but I paid the extra for the sake of the environment.] To go back to the analogy: The cars I drove are ones most Americans would be pretty familiar with. If I think about "the car market," I'm thinking about regular vehicles. I may hate the fact that Americans drive large trucks and SUVs, paying extra and keeping fuel economy down. And I don't love that when I go to purchase a car there are fewer sedan options and fewer good fuel economy options than there should be. But that is the extent of how much I think about "the car market." When my son brings up things like Maclarens, Bentleys, even Porsches, I don't have any interest. Luxury and super luxury cars just aren't something I think about. I'd probably feel differently about Maclarens if there was some kind of program subsidizing them for low income car buyers. ( Then I'd be incensed that people were being handed a car that was going to bankrupt them in fuel and maintenance costs.) How I Feel About NPC How I feel about luxury cars is how I feel about NPC: It just isn't relevant to me. When I think and talk about "the Salesforce ecosystem" or "the Salesforce platform" I'm considering the features and functions that most organizations use. Anything behind the Industries barrier is too niche or too expensive for any of my clients and for the majority of other admins and users out there. You Can Feel How You Want I've also gotten pushback from consultants that are working with NPC. They let me know I'm too harsh or too negative and that they're using it with their clients. That's fine. To be clear, those are two very different assertions: If I'm too harsh or too negative, I'm open to hearing the ways in which my analysis of the features or functions is wrong. For the most part, other consultants have not pushed back on those things. In fact, they pretty much all tell me I'm spot on. And of course there are consultants using Nonprofit Cloud for their clients. But those are much larger clients than I have, larger than 90% of the market. I've said repeatedly that this might be viable for large organizations. I don't think I've heard from anyone that they're implementing for a small or medium client and finding that it makes sense. They may be doing it, but they're having to build workarounds and figure things out in all the ways that I've pointed at. Can it be done? I'm sure it can. Will it be expensive? Yes. Will the client be happy and use the system long term, recommending it to their peers? Only time will tell.
- Barrier to Entry
Once upon a time it was relatively easy for a small nonprofit to self-implement Salesforce. It's how I got started , and many other nonprofit Salesforce professionals as well. We were working at a small organization, we needed CRM, and "this Salesforce thing" seemed like it could work for us. We spun up a trial org, applied to the Power of Us program , spent some time playing in Setup, possibly spent a couple thousand dollars on a "quick start" with a consulting partner, and we were off and running. The quick start consulting engagement was optional, but, at least in our case, it gave us a boost and some confidence that I was getting things right. Once Trailhead launched in 2014 it became even easier to self implement because that is one amazing free (and fun!) learning resource . Naturally, success on the platform varies. And the quality or scope of an in-house DIY implementation is going to be a lot different than you would get from a big partner project. But for basic fundraising tracking needs and an upgrade from spreadsheets, the Nonprofit Success Pack (NPSP) is pretty great for the needs of thousands of organizations. And as your in-house person grows their skills, it's easy to grow your Salesforce to support more and more of the business needs. ⚠️ Self Implementation: Would Not Recommend ⚠️ But in 2024 I don't think I would recommend that a nonprofit self-implement Salesforce. It's become much more challenging than it used to be. I won't say it's impossible because I believe that a motivated person nonprofit staffer with some level of technical comfort (not yet "expertise," but a willingness to try things, learn, and dive in) could do this on her own. With time to devote to the project, engagement with Trailhead and the help documentation, and a willingness to engage with the community and ask questions, a newcomer could implement a credible NPSP setup for their organization. Of course, the organization would have to allow that staff member to devote time and energy to the implementation. It's the amount of time required that has gone up significantly. Full Disclosure (if you didn't already know): I make my living implementing and supporting Salesforce for small nonprofits. Clearly that means I have a bias toward someone hiring a consultant for an implementation rather than doing it themself. So take my comments/opinions here with that in mind. But I'll give the reasons for my thoughts and let you decide. That Was Then What I remember of our Quick Start in late 2012/early 2013: We got 40 hours of consultant time for a prepackaged implementation with minimal customization. The "quick" part meant that customization was limited, but we also got something of a discount, or at least a fixed price. I remember it costing $5,000 or $6,000. (40 hours at $150/hr sounds about right.) That was 12 years ago and inflation is real. But I don't think too many consultancies are offering a basic implementation even for the inflation-adjusted equivalent of about $8,000. The Salesforce platform has evolved, of course, with more powerful automation through Flow and new products and services that organizations may need advice about. An organization probably has more acute questions when starting their Salesforce journey, as I'll talk about below. And it's just a different landscape with nonprofits served by the Industries vertical within Salesforce rather than a nominally-independent Salesforce.org. All that is to say that I am clear-eyed about how organizations will relate differently to their implementation partner than they might have back then. A small org that just "wants to start using Salesforce" may actually need more time from their consulting partner than would have been needed in 2012. or have a lot more to figure out on their own then they would have back then. This is Now If you're thinking about implementing Salesforce at a small nonprofit today: You have to choose between Nonprofit Success Pack and Nonprofit Cloud. As I've written , NPC isn't appropriate for small nonprofits. But should a small nonprofit choose NPC, I really don't think self-implementing it is viable. The data model is too complicated, the initial setup steps are too numeous and finicky, and the documentation is not complete. Members of the nonprofit Salesforce community are working on this, as is Salesforce itself, one assumes, but I have doubts that it will ever be possible to self-implement NPC. You also, at this very early stage in considering your implementation, will start getting calls from Account Executives, or AEs. ( Spoiler Alert: AEs are Salespeople .) Because of the way sales incentives are structured at Salesforce, you're going to get a lot of pressure to buy things like Unlimited Edition, Experience Cloud, Premier Support, and more. You don't get to convert a trial org into your real instance. You can get a trial and play with it, but when you get your real instance it will be essentially a clean org, perhaps with NPSP installed, but only the package, none of the extras that were part of the trial, including record types, sales processes, page layouts, metadata records for NPSP features (like reciprocal relationships settings), and more. The Salesforce platform and ecosystem has also grown in the last decade. So it's just the case that there are more decisions to be made, more features to consider, and more rabbit holes in the Setup Tree to explore than there were in 2012. I Just Went Through This Hours Though I do a lot more ongoing support and add-on builds, every so often I get to do an implementation from scratch for a new Salesforce org. I just got to the end of one of those projects, in fact. So let me give a transparent view into that recent implementation. (Other than not telling you who the client was, because that feels weird.) To begin with, I estimated the project at around 60 hours . With the benefit of hindsight, that might have been a little low, and I'll probably estimate a little extra padding next time because I strongly prefer to overestimate and come in under. (Then again, these are estimates, so...🤷🏻.) As of the time of this writing, I'm six or seven hours over where I estimated. Plus I want to provide at least a bit of cushion for post-implementation support. As a businessman I have to decide what to do. But bottom line: This implementation went very smoothly, was not very complicated, and was for fundraising only. So sixty hours is just about the bare minimum I can imagine a new implementation requiring. I work quite quickly and have a lot of experience navigating Salesforce's back end. Consider what it would take for an internal employee doing this as a self-implementation and learning Salesforce as they go. Would that take them twice as long? Three times? More? If this is an employee suddenly adding Salesforce to other job responsibilities it might not entail additional line item costs to the organization, but there is definitely a cost for that person to take on the project. Costs Speaking of costs, I do projects like this as a time-and-materials project after giving my best attempt at an estimate. I feel this shares the risk equally between me and the client. Of course, some consultants might do this implementation for a fixed fee. And others might have a lower (or higher) hourly rate. I was charging $176.80/hour for this implementation. (Full Transparency: My rate is $221/hour for Salesforce work. I give nonprofits a 20% discount, hence $176.80. In 2025 my base rate will increase to $230.) So this fairly simple and smooth implementation will be about $11,000. Other Considerations Because I've been doing this for a few years, I have some tools that allowed me to speed things up. Using Copado Essentials makes planning, testing, and executing deployments much faster when I build in sandboxes. (And we always do that , right!?!) Copado ain't free , however. I also have a bunch of metadata saved that used to allow me to customize on top of the NPSP Trial. I couldn't use it the way I did in the past, but that stored metadata gave me a bit of a speed boost in getting the org looking the way I want it. I was able to push that metadata into the client's production org using Salesforce DX. I also built and stored a test and training dataset using Cumulus CI . No Salesforce newbie is going to have access to any of that, even if they have budget to spend. I think it's also fair to point out that I try to put more thought and effort to design and user experience than some other consultants might. So I suppose some time could be saved there. Your Mileage May Vary I'll end where I began: Salesforce is a powerful platform and NPSP is awesome for tons of organizations. But it's just not that easy to implement on-the-cheap anymore. You might be able to do it entirely in-house by a self-taught staff member. A small organization doesn't need a large consultancy. A small organization may not even need a small consultancy or even an independent consultant like me. The Salesforce community is vast and full of smart, talented, experience people, you might be able to get one of them to help you for free. (Though please be careful going this route. I have made far too much of my living cleaning up the mess someone left behind implementing for a nonprofit without understanding the business needs of nonprofits or the architecture of NPSP.) But my experience in the last few years has lead me to believe that someone is going to have to spend at least 60+ hours working directly on a new implementation , from discussions with stakeholders, scoping, and training to architecting and hands-on-keyboard setup and configuration.
- The Future of NPSP
I regularly hear people claim that NPSP is "on its way out," or "already dead," or "Salesforce is going to stop supporting it." None of those things are true. Could they become true soon, quickly, or without any notice? Yes, they could. But Salesforce could also decide at any moment to stop developing, kill, or completely change Nonprofit Cloud. Right now I don't think they are going to. But my point is that they could . Salesforce is a giant corporate capitalist enterprise. It fundamentally exists only to make money. If it isn't making money on nonprofits, or through the Industries model, or whatever, it will change what it is doing. And Salesforce is run by people, who can change their mind, or their business vision, or, for that matter, can change jobs. So if the people in leadership were to decide they didn't want to be in the nonprofit market at all, the company could exit it on a dime. If those people decided that the nonprofit price point should double, there is nothing tangible to stop that from happening. (And for the sake of future-proofing this article, I should probably also note that Salesforce could change the names of these and other products at any time.) Where was I...? Oh, right. Don't Listen to the Fear The Nonprofit Success Pack (NPSP) is not going anywhere. It's stable. It works very well for what it does. Thousands of organizations have it installed and use it every single day. Even if Salesforce wanted to kill it quickly, they could not. There would be a very long tail of organizations still using the product. Besides, Salesforce has repeatedly said that they intend to continue to support NPSP. Sure, we could decide not to believe them. But so far I see no reason to be quite that cynical. Those of you who know me know that I'm plenty cynical. I'm just not that cynical. I'm sticking, for now, with "Trust, but verify." Support for NPSP will continue, even though further development of it as a product will not. NPSP is Like Cars Let's face it, development of NPSP stopped a long time ago. Long before New Nonprofit Cloud was dreamed up. There haven't been significant new features in the core NPSP offering since Enhanced Recurring Donations, Customizable Rollups, and Engagement Plans and Levels, all of which are more than six years in the past. And some of those were just upgrades to existing functionality in the first place. But just because there hasn't been much development doesn't mean NPSP is somehow outdated. I would argue that development of NPSP slowed and basically stopped because it reached the point that it was meeting the truly common and shared needs of nonprofits. NPSP takes Salesforce, reconfigures the B2B data model to make it work for tracking individual constituents and their households ("B2C," in the lingo), gives us relationship tracking between people, relationships tracking to multiple organizations, and powerful flexible donation rollups. That's basically the common set of CRM needs for nonprofits. Everything else that Salesforce.org used to publish was for a subset of the market—for good reasons! The Program Management Module only works for the program model of certain kinds of organizations. Outbound Funds is great, but only if your organization needs to track...well...outbound funds. Etcetera. And I think this is OK. NPSP reached the point where it was doing what we needed and Salesforce.org realized that when they made new "products" it made sense for them to be optional add-ons, not additional bloat of the core product. Here's my analogy: What's fundamentally changed about cars in more than half a century? Basically they're boxes with four wheels that burn gas to move people around. We invented automatic gearboxes, seatbelts, brigher headlights, cruise control, fancy radar for lane keeping and collision avoidance, and backup cameras. But my great-great-grandparents would have no trouble recognizing today's cars and even taking them out for a spin. Even electric cars are just not that fundamentally different. [I can say this with confidence: I own one. It's great. But when you get down to it, it's just a car.] So I think the future for NPSP looks a lot like the last decade or so: It works great. It's stable. It runs on a state-of-the-art platform that you can customize to the nth degree. There are a zillion organizations (and people) using it. And there is an amazing community of practitioners that work with it and welcome new people to its use, teaching, coaching, and training them. I still think NPSP is the right choice for 95% of nonprofit organizations that are thinking about implementing Salesforce at this moment. And those that are already on NPSP should not be expecting to migrate off any time soon. On a Wild Ride Does any of this mean that the future for NPSP won't be a bit of a ride? No, of course not! Just as two years ago Salesforce pulled the rug out from under all of us by announcing that NPSP would be replaced with NPC, which would be an entirely new system and migration would require a complete org swap, there could be surprises in store for all of us. I'm just trying to remind you that this was always the case. This is where I believe in the power of the Salesforce Community, particularly the Nonprofit Community. We are scrappy, and determined, and smart. If NPSP stops looking viable, then we'll come up with alternatives, whether it's re-creating the core functions through a community-supported free alternative, or building tools, templates, and workbooks for migration. If we come up with some Must Have feature that NPSP lacks and Salesforce is never going to provide, we'll build it and find a way to release it through Open Source Commons, or UnofficialSF, or somewhere else.
- Bifurcating the Market
With the move to the new Nonprofit Cloud (NPC) Salesforce has made a very intentional decision that they want to divide the market for nonprofits using Salesforce into two distinct segements: large organizations and everyone else. (Side note: when I say "nonprofits," I generally mean "nonprofits and educational institutions." But that's too long to write every time.) Large Organizations For large organizations, NPC and EdCloud might be a good solutions (or might be so someday ). I think I've been clear in my prior blog posts like The Emperor's New Clouds , Extension Objects: There's Nothing to Like , and others, that I don't think the new clouds are All That. But let me assume that Salesforce will manage to fix (or paper over) the problems that I've pointed out. Clearly they're making investments in roadmap for the new clouds. So let me give the benefit of the doubt that eventually the new products will be desirable for organizations planning to adopt Salesforce and that orgs already on Salesforce will eventually see features of the new clouds that are compelling enough for them to want to migrate. (Reminder: If you're currently on Salesforce but want to adopt the new clouds, this is a complete re-implementation .) But barring changes that I can't imagine (and nobody I've talked to can see), the new clouds will still only be appropriate for large nonprofits . When I say "large nonprofits" or "large organizations" I mean universities, national or international nonprofits, foundations, large museums, and the like; organizations that can support a team of multiple Salesforce professionals, including developers, plus probably have cash for a lot of partner/consultant support as well. I really mean large organizations . The data model, back end setup, and feature set of Nonprofit Cloud and Education Cloud are just too complicated for even medium-sized organization to work with. So I say that these clouds might be useful for larger organizations because they can use their greater resources to take advantage of the technology in ways that others can't and to build a lot of customizations, workarounds, tools, training, and documentation that make the extra complexity of the products bearable. And let me be transparent: I don't work with large organizations and I don't have a lot of experience with what kind of setups they have. So I am giving this analysis from an outsider perspective. Given that the large organizations have so many more resources than smaller ones, I think it's probably appropriate (to some extent) that they spend more money and effort on their Salesforce org. They have needs around scale and complexity that would always result in more expensive implementations. Plus, from my perspective, large organizations have (or should have ) the resources and expertise (or can hire/contract it) to caveat emptor. (That means "Buyer beware.") Everyone Else Then there is everyone else that might want to use Salesforce in a nonprofit context. This means small and medium nonprofits. This probably means you , dear reader, or the majority of your clients. I can't say this more strongly: The Nonprofit Success Pack (NPSP) is the right solution for you . (I suppose that comes with a small asterisk. If you're too small, Salesforce itself might not be right yet. Perhaps you should just stay on spreadsheets for a little longer. And there are plenty of organizations that need neither NPSP nor NPC because they should use plain Sales Cloud or Service Cloud or a completely custom other configuration. ) "We're going to become the Red Cross of [insert niche here]!" I know that medium sized nonprofits often think they're going to become large ones someday. Certainly that's the hope of many a founder and CEO/ED of these orgs. It feels like my duty to point out the improbability of this. And anyway, until you are large—really large!—NPC is not a good fit for you. Not today and not, in my estimation, for at least five years (and probably longer). So, yes, plan your system with the future in mind, design for scale, and leave room for growth. But build a system that works for your org as it is today. Don't saddle yourself with overbuilt and extra expensive. If you have a system that doesn't work for your org today you're going to struggle with adoption in the first place. The Nonprofit Success Pack (NPSP) works great. It's easy for users to understand, has many features you and your users will appreciate, and can handle quite a lot of volume. If you really truly do get large someday, such that either you're hitting the limits of what NPSP can handle at very large scale or else just that you have grown to the point that you think you meet the criteria I laid out, above, for using NPC, then and only then would it make sense to go with NPC. Choosing NPC while you are small or medium sized because you hear all the hype from Salesforce about the "innovation" and "exciting roadmap" is not going to serve you well. As I did last week , I'm going to reach for a vehicular analogy: Buying NPC today is like buying a school bus when you have your first child because you're planning to have lots of kids. You'll spend years driving an enormous vehicle that's practically empty. And by the time you've gotten to that giant brood, we'll probably all be wearing personal jetpacks anyway. (One can hope!)