Nerd @ Work

When Salesforce is life!

[Salesforce] Read this before you perform your Salesforce Data Migration

Let’s talk about Data Migration in Salesforce with Priscilla Sharon, Salesforce Business Solution Executive for DemandBlue.

DemandBlue is in the business of helping its customers maximise their Salesforce investment through predictable outcomes. As we thrive in an era of cloud-based Infrastructure, Platform and Software services, DemandBlue has pioneered “Service-as-a-Service” through a value-based On Demand Service model that drives bottom-line results. They foster innovation through “Continuous Engagement and On Demand Execution” that offers their customers Speed, Value and Success to achieve their current and future business objectives.

Their On Demand Services for Salesforce include Advisory, Development & Customization, Integration, Administration & Support, Maintenance, and Lightning Migrations.


Salesforce Data Migration – Imagine if you were traveling to an exotic new destination for the holidays. You want to make sure that everything is perfect and that nothing goes wrong. You might want to take all the precautionary measures – get travel insurance, have emergency info at hand and make sure that you pack all the necessary things without leaving anything behind. You know there could be nothing worse than reaching the airport only to realise that you forgot your passport – Sigh! But you also know that you don’t have to go through these hassles with careful planning and preparation, which can make it a safe and wholesome vacation for you.

Just like traveling from one place to another, migrating data from one place to another be it from Excel Spreadsheets or Legacy systems to cloud, needs utmost care and caution throughout the scope of migration in order to avoid any mishaps. And ensuring practical safety tips might just save you from the glitches in your Data Migration plans. So, here’s a quick 6-point checklist – your passport to a safe and successful Salesforce Data Migration journey.

6-point Checklist for Successful Salesforce Data Migration

  1. Engage the Stakeholders: It is critical that you involve your stakeholders and inform them well in advance before migration to ensure that you gain maximum support for the project. Stakeholders from different teams and departments have profuse knowledge of the data and can give actionable insights pertaining to your Salesforce Data Migration plan.
  2. Identify the Data to be Migrated: Stakeholders are aware of the most crucial data and clarify your uncertainties regarding the data structure, the place of storage, if it has any duplications and its effect on the Salesforce Data. It might require you to create new or appending current data fields, validations and field values in Salesforce.
  3. Create a Backup – Most importantly, create a data backup to perform a rollback to recover from any possible errors. With a Data Backup, you can be double sure that you can go ahead with the migration process, so if at any stage there is an issue, you know you have the original data to fall back on.
  4. Prepare Data for Error-free Data Migration: After deciding on the changes to be done in step 2, now you can make the necessary adjustments to ensure error-free Salesforce Data Migration process. You can add or modify objects, fields, workflows and validations.
  5. Run a Test Migration: You don’t want to back out after importing all the data into the system. So, to avoid risking data in production, it is highly recommended that you run the test in a Sandbox environment to fix possible issues.
  6. Migrate Data: The test Migration gives you the confidence to migrate data into the production environment. Inform your stakeholders about the changes and how it will affect them prior to migration. Post your Salesforce Data Migration process, it is crucial that you validate the data.

How to Prepare for Salesforce Data Migration?

Each and every Salesforce Data Migration project is unique. Therefore, different migration may need different tools and resources. Having said that, here are top considerations to incorporate in any Salesforce Data Migration strategy.

  1. Identify the Team Members to be involved: Besides the stakeholders, you need to consider the admins and developers who need to be involved in the Salesforce Data Migration process. You will need to include the end-users who will work with the data.
  2. Start Early to Start Early: A Salesforce Data Migration plan is typically a part of a larger project. So, an early start would mean the early start of the big project you have planned. You need to identify, prepare, clean, restructure and map data well ahead of time.
  3. Build an adequate amount of time into the Schedule: Salesforce Data migration instances will have many exceptions, and you need to be prepared to meet them. Unexpected issues may surface when you practically work with the data. People may skip steps to meet the deadlines if your schedule is unrealistic. You need to remember that getting it right is as important as getting the work done on time.
  4. Designate tasks to the right People: You need to avoid assigning too many of the members on a task or inviting too many people into a discussion. Ensure that you assign each person’s role after you identify the people to be involved.
  5. Identify the Right Tools: Salesforce has quite a number of tools for Data Migration. In certain scenarios, an organization may require tweaks to be made to an existing tool or to develop a new one.

Enjoy this great infographic!

Have a safe journey with DemandBlue…

Salesforce data migration involves critical decisions since it is typically a small part of a bigger project. Though data migration may be a subset of a larger project, it’s no small task, and the end result can make or break the success of the bigger project. Hence, Salesforce offers cutting-edge data migration tools, such as Data Loader, Data Import Wizard along with Third-party apps that help automate Salesforce Data migration. However complex projects may require an experienced Salesforce Data Migration Consultant who has existing tools or can develop them based on an organization’s specific requirements. And we at DemandBlue have been a preferred Salesforce partner for our one-of-a-kind On Demand Solution for Salesforce. On Demand is a unique Service-as-a-Service model where businesses can deploy Salesforce projects without the hassles of costly contracts or complex SOWs; our clients are charged only for the number of hours spent on a project – be it 40 hours of effort spread over a week or two or a 100 hours of effort spread over a period of a month or two, the customer is billed only for what is consumed.

To find out how On Demand Service model for Salesforce can add Value to your next Salesforce project, Talk to DemandBlue team now!

[Salesforce / Mail Marketing] How to generate leads using drip email marketing?

In this post we’ll talk about email marketing, a subject that rarely has been seen in this blog. I’ll leave the speech to Siva Devaki.

Siva Devaki is a technocrat and an entrepreneur who is passionate about bringing value to the customers with creative technological solutions. Siva currently busy in growing his technology startup – MassMailer, a simple and easy mass email app for Salesforce CRM customers. Siva is passionate to write articles, blog about email marketing, sales development, email deliverability best practices. You can find Siva’s LinkedIn profile at www.linkedin.com/in/sivadevaki .


With click-through rates 300% higher than other email marketing campaigns, drip email is one of the highest ROI strategies a company can invest in. Yet running the right drip marketing campaign requires a comprehensive strategy — it isn’t as easy as “set and forget.” Here’s what you need to know about generating leads through scheduled, automated emailing.

How to generate leads using drip email marketing?

The Advantages of Drip Email Marketing

A drip email marketing campaign is a sequence of emails that are sent to leads in order to generate interest and build a relationship. There are a few core benefits to a drip marketing campaign:

  • Drip marketing builds a relationship over time.
  • Drip marketing is fully automated.
  • Drip marketing is a cost-effective form of marketing.

One of the reasons email has such a high ROI is that it’s both effective and cost-effective. A drip email campaign is able to take advantage of these benefits to continuously engage leads and encourage purchasing.

Creating a Drip Email Marketing Strategy

At its heart, a drip marketing campaign is about sustaining long-term contact with your customers. An email newsletter that is sent out every morning with important, interesting and insightful content will remind your customers that your company exists — but also runs the risk of over-saturating your customers and flooding their inbox. Meanwhile, a marketing campaign that sends information about good deals coming up over the weekend can be equally as valuable.

Drip campaigns can also be automated to reconnect with customers at key points of their journey, such as emailing customers who have unsubscribed from a service inviting them back or emailing customers who have abandoned items within their cart. A drip strategy must include the frequency of emails as well as the content of these emails and can be integrated into customer relationship management suites for better responsiveness and personalization.

Tips on How to Generate Leads through Drip Emails

  • Consider letting leads choose their own email frequency. For newsletters and deals, the frequency can be at a monthly, weekly, or even daily level.
  • Pay attention to your lead generation statistics. How often are leads clicking on links? Are they opening emails or deleting them? Are trends moving upward or downward?
  • Provide good content. If you want your leads to open your emails rather than deleting them, you need to provide the content that they want — not the content you want to give them.
  • Identify the right times of the day. Before work and after work are usually the best time to send emails, but your demographic may vary. Checking your statistics and testing out different types can help.

MassMailer for Drip Marketing Campaigns

MassMailer provides complete campaign automation, statistics, and email template builder for drip marketing campaigns. Through MassMailer, you can easily send emails out on an automated basis to your Salesforce leads, leveraging built-in templates (or building your own). MassMailer provides the statistics that you need to determine whether your drip marketing campaigns are working, while also helping you avoid traditional limits on Salesforce emails.

A drip email campaign will build your relationships with your customers, creating brand awareness and supporting your brand identity. Through scheduled, automated emails — and with the help of MassMailer — you can encourage conversions and improve your email marketing ROI. 

[ORGanizer] Reindeer release: cool new features and a special gift from The Welkin Suite

The ORGanizer for Salesforce Reindeer Release is finally live!

Thanks to the guys of The Welkin Suite we have a special gift for all ORGanusers: an amazing 40% discount if you start a subscription from within the TWS ORGanizer’s banner! 

To discover how to get it, follow this post!


The Welkin Suite 40% discount

Before discovering all the new features of the Reindeer Release v0.6.8.0 let’s see how to get the 40% discount for The Welkin Suite subscription.

Make sure you have the latest ORGanizer for Salesforce version (right click on the ORGanizer icon > Manage Extensions):

Now click on the ORGanizer for Salesforce icon to show the Popup page and identify The Welkin Suite banner:

Click it and the promo code will be automatically added to your basket on the Welkin Suite site!

If you have purchased ORGanizer PRO, drop me a line using the support form, I’ll send you a dedicated promo code.

Reindeer Release new features

New PRO license limits

If you purchased a PRO license (available only on Chrome version) you’ll now get increased storage limits:

That is you can store up to 2000 logins (sync or not) and up to 1000 sync logins: the Beta limits are 200/150, but the free tire limit will get lower once the ORGanizer gets out of Beta!

Profiles Chamber

Want to massively change profiles? With the Profiles Chamber plugin you can!

In this release the plugin only supports Login Hours massive update with different options and the chance to create templates for a given Org).

You can choose multiple profiles and days to update and then apply changes (by deploying in your ORG): only the Login Hours data is actually pushed.

For detailed info about the Profiles Chamber follow this link.

Replace API names refactoring

The Replace API Names plugin has been completely rewritten to give consistency between Classic and LEX:

The API name is now shown directly next to the real label: few bugs has also been fixed (e.g. misbehavior with fields with the same label).

[Salesforce / Interview Tips] Preparing for a job interview as a Salesforce Administrator

 
Becoming a Salesforce Administrator is often the entry route into the world’s number one CRM technology, but this doesn’t make the job interview process any easier for prospective admins.

As the most prominent role in Salesforce, the competition for a job as a Salesforce Administrator is particularly high. In Mason Frank’s 2018/19 independent Salesforce salary survey, 70% of respondents reported being a Certified Salesforce Administrator, far higher than any other certification. With other candidates waiting in the wings, you need to be sure your interview goes perfectly to guarantee the job offer, and that comes down to preparation.

A job interview for a Salesforce Administrator role can take many forms, and so you’ll need to be prepared for several different lines of questioning. Your interviewer won’t just be interested in your technical experience as an administrator, they’ll also want to know how you see CRM as part of a larger business, and use this to test how much you’ve researched their organisation. In addition, they’ll also want to get to know you as a person.

Read on for a series of tips on how to prepare for your next job interview as a Salesforce Administrator.

Testing your technical knowledge

Ultimately your prospective employer will want to learn how skilled you are on the Salesforce platform, and so you should expect to be asked technical interview questions. A Salesforce Administrator is quite a varied role, and so technical questions you may be asked can be quite broad. You could be asked something very functional such as ‘what is a roll-up summary field’, or perhaps something a little more scenario-based, such as ‘how do you share a record and in what circumstances would that be expected?

One thing that you need to be aware of going into the job interview is that your interviewer may have no experience using Salesforce, or alternatively they may be a Certified Technical Architect.

With this in mind, it’s not enough to simply have a good working knowledge of Salesforce, you need to be prepared to explain technical concepts in plain language so that a non-expert will understand you. Having technical knowledge is one thing, but being able to communicate your knowledge to a layman is another thing entirely, so practice this before the interview.

Testing your experience

While knowledge is valuable, application is power.

Salesforce Trailhead is a fantastic education portal and is responsible for launching the career of thousands of Salesforce professionals, but it won’t provide you with that all-important practical experience that employers are looking for. This is why experience is incredibly valuable, and so you should be prepared to discuss the projects you’ve worked on and what you learned from them.

If you’ve worked as part of an implementation team, be ready to discuss the technical elements as well as the challenges you faced and how you overcame them. If you’ve ever experienced data loss or a data breach, be ready to discuss how you discovered the event and how it was resolved. Don’t be afraid to discuss challenges and mistakes made—this is what experience is all about, and will set you apart from the other candidates.

Something else that employers value highly is your ability to work on a collaborative project. As an Admin it’s unlikely that you will be working completely independently, so be prepared to talk about your communication skills, requirements gathering, and ability to work within the confines of a project timeline, using examples from your previous experience.

Testing your cultural fit

It’s essential you have the skills and experience to perform the job you’re being interviewed for, but your prospective employer will also want to get an idea of who you are as a person. After all, they’ll likely be spending around 40 hours a week in your presence, so it’s important they employ someone who they’ll enjoy working with—you should also be confident that you’ll enjoy working with them as well!

Given that your technical knowledge and experience come with the territory of being a Salesforce professional, getting your personal character across can often be the most nerve-racking element of a job interview, but this shouldn’t be the case. Just be yourself and communicate your goals and ambitions clearly.

It’s always a good idea to think about why you entered Salesforce technology and where you eventually want your career to take you, as long as you can relate this to why you want the job you’re interviewing for and how this will help you achieve your goals.

Being a successful Salesforce Administrator is about more than just doing the job, it’s about finding ways to maximise the value of Salesforce in an organisation, and making yourself indispensable as a result.

[Salesforce] How to safely get the logged in community user from Einstein Bot

 
Few weeks ago I blogged about Dealing with the running User on Einstein Bot dialogs.

One of the questions I got from the community was:

is this approach safe for production?

I was actually not sure about this, as the logged in info was passed from the pre-chat page to the chat bot context in clear: this way an advanced JS hacker could have impersonated a real user, knowing its username/user id: that’s why I replied that you should have used a temporary “token”, that should have been deleted once used (upon user confirmation on the Chat Bot loading step).

When I write posts about tech workaround all I have in mind is open your minds and make you find a new way to solve problem: from this point we can enhance our solution to make it the best one!

Few days ago Arthur Imirzian contacted me to read his new article on his blog: How to safely get the logged in community user from Einstein Bot.

This blog was the direct consequence of my workaround, making the user identification safer.
He then went on by finding another workaround to enforce user authentication with this great post!

I loved his quick and dirty style and I decided, upon his approval, to repost his article here.

Enjoy the reading!


Kerckhoffs’s principle says that a cryptosystem should be secure even if everything about the system, except the key, is public knowledge. The user id is not a key and shouldn’t be considered as one.

Both classic Live Agent client and Snap-Ins chat client provide a very useful feature to pass the prechat information to the custom fields on LiveChatTranscript object.

As you know, Einstein bot is built on top of Live Agent and allows you to trigger apex actions based on community user message like a knowledge article search. Problems come when you want to make authenticated actions like updating your case status or contact information. Live Agent doesn’t provide any way to enforce logged community user session. Instead, the context user is a technical user (AutomatedProcess or Integration).

The first reflex is to get the user id from a visualforce page / lightning component and pass it to the Snap-Ins Code Snippet in order to reuse it from apex by querying the Transcript Object. This approach is a security breach as the user id can be easily changed on the fly. The attacker can usurp any user by providing another user id. Again, user id is not a private key and shouldn’t be used as one.

A safer approach

So we need to find a way to validate that the returned user id is equal to the connected user id. The idea illustrated below suggest asymmetrically hashing the user id so no one can change it to usurp someone else’s identity. As the end user cannot produce a token, it can’t corrupt the user id.

Step 1: Token generation

The first step is about token generation based on connected user id. The user id will be publicly accessible but we will use a self-signed certificate to sign the user id and generate a token.

Go to Setup > Security > Certificate and Key Management > Create Self-Signed Certificate, define a label, a unique name, uncheck Exportable Private Key and click on save.

Use the apex code below to generate a secure token based on session id and user id of the connected user.

public static String getToken(String keyToSign){
    if(keyToSign == null){
        return null;
    }
    return EncodingUtil.base64Encode(
        Crypto.signWithCertificate(
            'RSA-SHA256',
            Blob.valueOf(keyToSign),
            'LightningComponent'
        )
    );
}

Step 2: Get the user id and the token

Add the lightning:prechatUI interface to a Lightning component to enable Snap-ins to identify it as a custom Lightning page template that can be used for the Snap-ins Chat pre-chat page (docs here).

Now call the getPrechatData method from your lightning component to retrieve the logged user id and its token.

@AuraEnabled
public static Map<String,String> getPrechatData() {
    Map<String,String> prechatData = new Map<String,String>();
    // Returns the context user's ID
    String userId = UserInfo.getUserId();
    prechatData.put('userId',userId);
    String token = getToken(userId);
    prechatData.put('token',token);
    return prechatData;
}

Step 3: Pass the prechat information

LiveChatTranscript is the unique object that can be used to share context between the logged user and Eintein Bot which means that we need to create custom fields on LiveChatTranscript object.

Go to Setup > Object Manager and search for the Live Chat Transcript object. Then Field & Relationships to create two new custom fields called UserId (UserId__c) and Token (Token__c).

Now we have retrieved the user id and the token from step 2, we can pass them through a snippet setting file.

Add the code below to your existing Snippet Settings File you had uploaded as a static resource.

embedded_svc.snippetSettingsFile.extraPrechatInfo = [
    {
        "label":"UserId",
        "transcriptFields":[ "UserId__c" ],
        "displayToAgent": false
    },
    {
        "label":"Token",
        "transcriptFields":[ "Token__c" ],
        "displayToAgent": false
    }
];

Don’t hesitate to visit Nerd At Work’s blog for more details.

Step 4: Validate the token and trust the user id

This is the last step before we can rely on the returned user id. We need to ensure that nothing has been corrupted. We’re going to sign the user id returned by the lightning component again and compare this new token to the returned token.

public static Boolean validateToken(String userId, String token){
    return token == getToken(userId);
}

If the user id was corrupted by the end user, signing it again will produce a different token than the previous one. If not, it means we can now rely on it.

Conclusion

We just described how to safely get the connected community user id from a live agent session. And remember you should never trust user input, your user will not always submit data your application will expect.

What’s the next step ? First pass the Einstein Bots Basics module and then jump to the second article about authenticated DML operation from Einstein BOT.

[Salesforce] Single or Multi-Org – What is your Salesforce architecture?

 
Let’s talk about single vs multi org architecture with Priscilla Sharon, Salesforce Business Solution Executive for DemandBlue.

DemandBlue is in the business of helping its customers maximize their Salesforce investment through predictable outcomes. As we thrive in an era of cloud-based Infrastructure, Platform and Software services, DemandBlue has pioneered “Service-as-a-Service” through a value-based On Demand Service model that drives bottom-line results. They foster innovation through “Continuous Engagement and On Demand Execution” that offers their customers Speed, Value and Success to achieve their current and future business objectives.

Their On Demand Services for Salesforce include Advisory, Development & Customization, Integration, Administration & Support, Maintenance, and Lightning Migrations.


While setting up a Salesforce architecture or assessing the performance of an
existing org, the most perplexing question that haunts anyone is to decide between
single-org architecture and multi-org architecture. An organization in Salesforce is
meant to be an instance that lets users access, deploy or create applications with
various feature sets. An organization strategy should also include a plan to identify
the right Salesforce partner to customize your org architecture for your unique
business needs.

With new features added to Salesforce in the  Salesforce Spring ’18 Release , you
obviously cannot make a decision based on your own whims and fancies or personal
experience, but rather need to weigh in the pros and cons of each instance carefully
before taking that final plunge. A safe way to navigate this challenge is to have
Salesforce partner with the experience and expertise to provide guidance.

The few elements that you need to keep in mind are the need for customization or
standardization, the complexity of integration (Learn Salesforce Integration Best
Practices from 7 Integrations to sync your CRM with all phases of the customerlifecycle), cross-business collaboration and costs. Keeping in mind all these factors,
you need to establish a strategy beforehand, which will save your business from
incurring an unnecessary loss.

In an effort to throw some light on this question, let us walk through the benefits and
risks inherent to each Salesforce architecture model, and which org will suit your
business the best.

Why Single-Org Salesforce Architecture?

Sing-org strategy works best if you are looking at either of the below 2 key essentials:

  • Standardize business processes
  • Merge/Acquire another company using Salesforce.com

Benefits of Single-Org

The major benefits you can derive from a single-org are listed below.

Greater Management Visibility – If you are looking to have a clear linear picture of the entire business process, it is facilitated by the availability of:

  • Roll-Up Reporting
  • Global drill-down into pipeline & activities

Standardized Processes – You can streamline all your processes with organized workflow pattern and this includes:

  • Lead Management
  • Opportunity Management

Collaboration – Create transparency in the business process by allowing for the below features:

  • Know what everyone else is doing
  • Realize synergy among business units
  • Avoid duplicate effort & conflicts within accounts

Global Standardization & Economies of Scale – Easy to setup and follow best practices and global standards:

  • User Training
  • Application Release Management
  • Application Integration
  • Data Management

Regionally Personalized Configuration – This is achieved through:

  • Granular security model, multiple profiles, records types, page layouts, sharing groups
  • Translation Workbench

Single-Org Risks

Org complexity could become a barrier to progress and this includes:

  • Potential to hit specific Org limits
  • Org-wide settings (e.g. security and sharing) could become difficult to govern and manage
  • Runtime processing could be impacted by volume of code deployed

Why Multi-Org Salesforce Architecture?

Go for multi-org if you have multiple processes and want to fundamentally separate business processes for similar BU’s. Also get legal/regulations on data privacy and sharing and support for different processes by BU/Region that cannot be standardized.

Benefits of Multi-Org

  • Record Sharing and Security model is simplified by non-complex sharing rules
  • Provides greater BU autonomy through individualized processes and customized functionality
  • Greatly reduces the risk of exceeding Org limits (Tabs, objects and code lines, Runtime governor and API limits)
  • Org-wide settings are easier to govern and manage
  • Lower data volumes within a single Org potentially improves performance
  • Improved time to market and the freedom to innovate
  • Fewer teams impacted by shared updates
  • Reduced complexity within a single Org

Multi-Org Risks

  • Harder to get a clear global definition of processes and data.
  • Less reuse of configuration and code.
  • Customization required to deliver unified reporting across Orgs.
  • Duplicated administration functions required.
  • Increased complexity for SSO.
  • Third-party license costs increase depending on the solution.
  • Salesforce Integration cost increases with process & data integration across Orgs.

As more Organizations are adopting the latest Salesforce features like Lightning to gain the competitive edge, it is crucial that you consider the above guidelines when you sit down to make that crucial decision on the type of Salesforce architecture that you need.

It doesn’t harm you to have a reliable Salesforce partner like DemandBlue to provide insight and support to accomplish this. Talk to us!

[Salesforce / Interview Tips] Preparing for a job interview as a Salesforce Developer

 
Salesforce Developers possess a strong working knowledge of the platform and can add serious value to a business. But given the competitive talent market, you must be prepared to set yourself apart from your peers to really stand out during a job interview.

While job interviews can take many weird and wonderful formats, you should be prepared for two different types of questions during the interview. One will test your technical competency for the role, and the other will measure your experience and knowledge of CRM development in a commercial environment.

Technical questions during the interview

Firstly, the interviewer will want to get a grasp of your technical understanding of the Salesforce platform, so be prepared to answer questions around the architecture or processes involved in Salesforce development.

This can be slightly daunting, as you’re essentially being tested to see whether you really have the skills that are listed on your resume, but there’s no reason to be intimidated. If you’ve worked as a Salesforce Developer in the past, particularly if you’re certified, none of these questions should be outside your realm of understanding.

If you do struggle with a question, there’s nothing wrong with admitting you’ve never worked with that particular tool or concept before—the interviewer will appreciate your honesty, as some people would try to bluff it in this situation (and make themselves look silly in the process). You could even ask them about it, which would show you’re always looking to learn.

If you’re nervous about the kind of questions you may be asked during the interview, we have a resource that details technical interview questions for Salesforce Developers, based on our experience as a specialist Salesforce recruiter. It’s unlikely the interviewer will ask you something incredibly technical, but it’s nice to be prepared just in case.

Experience-driven questions during the interview

As well as what you know, the interviewer will also want to find out what you’ve done so far in your career, and how your experience makes you the perfect candidate for their job. How did you become a Salesforce Developer? What kind of projects have you worked on in the past? What has been the biggest challenge in your career so far and how did you overcome it?

The best way to prepare for this line of questioning is to revisit your portfolio and map out your entire learning journey. A small project you worked on three years ago could be incredibly useful for the task at hand, and so you should be prepared to recall what you did and why.

This is especially useful if you can map it against your education journey—how much did you know at that stage of your career and what would you do now that’s different? Base this around what you’ve learned, the training you’ve undertaken, and the certifications you’ve gained since then.

There’s also merit in talking about mistakes that have been made on projects in the past and how they impacted development. The fact you’ve identified these mistakes and now know better is a testament to the knowledge and experience of your role. Remember that experience is not inherently nominal—a developer with three years of experience who has worked on complex projects will be more valuable than a developer with five years of experience who hasn’t.

Five quick tips for interview preparation

To interview successfully, it isn’t all about having an answer for whatever question is thrown at you. There’s also an onus on you to do your research and find out exactly what will help you stand out in the context of the position you’re applying for. Consider the following:

  • Find out which Salesforce product/edition/instance the company is using — if you don’t know which product you’ll be working with, how can you convince the interviewer that you’re experienced enough to develop on it?
  • Find out what format your interview will take — some interviews are relatively informal chats, whereas some involve practical exercises such as development tasks or challenges. Clarify this before the interview to avoid being blindsided.
  • Focus on how taking this job would benefit both parties — as a Salesforce professional, you’re always looking to improve your career standing. If you can identify what it is about this particular company/role that will help you achieve your long-term career goals, telling this to the interviewer will showcase your ambition and drive.
  • Avoid using overly technical language — in some cases, your interviewer won’t actually have a strong knowledge of the Salesforce platform, and so speaking in technical terms won’t demonstrate your point the way you’d like to. Without being patronising, be prepared to communicate complicated concepts in simple language. This will also demonstrate your comprehensive understanding of the Salesforce platform.
  • Identify the company’s revenue streams and demonstrate how you can optimise them — while a company will value a lot of things, the bottom line is turnover. If you can demonstrate, based on experience, the value you can add to the business and the potential return on investment in you, the interviewer will start to see hiring you as an essential financial decision—you’ve become indispensable before you even sign the contract!
  • Preparation is key, but nobody is immune to a bad interview—sometimes you and the company simply won’t be a good fit, and this is fine. Whether successful or not, it will be valuable experience that you can take forward in your Salesforce journey, so don’t be discouraged if things don’t go to plan. Just remember to approach it with a level head and confidence in your ability. You have skills that this company needs, otherwise they wouldn’t have invited you in to interview in the first place!

[Salesforce] Dealing with the running User on Einstein Bot dialogs

 
As part of the Salesforce Solutions Team at WebResults I spend some time training myself on new products and trying to build POCs (prove of concepts) to give value to the training and promote the knowledge inside my company.

I recently was playing with Einstein Bots and got stuck when needed to identify the running user, when dealing with queries to get actual user info from the CRM.

I though it was enough to call the UserInfo.getUserId() method and I could get who is the user calling the bot, but unfortunately the running user of an Apex InvocableMethod is the AutomatedProcess user, that you can monitor from Setup > Debug Logs > User Trace Flags [New] as shown below:

I believe that Salesforce will add this feature in the next feature but I had to find a workaround.

The Workaround

I started a thread on Stackoverflow, where I got some ideas but no solution at all.

After a while I came up with a dirty solution that allowed me to know the exact user logged into the community. I won’t explain all the trial and errors but the whole solution, with some code samples.

Here is the list of actions:

  1. Enable Pre-Chat
  2. Override Pre-Chat with a Lightning Component
  3. The Pre-chat Lightning component calls its controller to get if there is a valid running user and returns back all the data needed for the prechat
  4. The Lightning component compiles all the needed inputs for the pre-chat (e.g. name, email and username) and submits for the chat: if the info are found, the component hides the pre-chat fields (that may be filled by a non authenticated user)
  5. The info submitted are written on the Transcript object
  6. An Einstein Bot dialog examines the Transcript object using an IncobaleMethod of an Apex class and determines which is the running user
  7. The bot can now change its behavior depending on the fact that the user is logged or not

To get all of this working you need 2 custom fields:

  • A custom field on the Contact/Lead record (we’ll call it Username__c) that is used to configure the prechat on the Snap-In
  • A custom field on the LiveChatTranscript object (we’ll call it Username__c as well) used to store the info got from the Pre-Chat component

Once fields are created, we need to setup the Pre-Chat page on the Snap-in settings related to the bot:

And setup the Pre-chat page:

Now let’s create the Lightning component that will replace the Snap-in chat (configured in the picture above):

prechat.cmp

For the what & whys plese refer to the official documentation in this link.

The component uses the lightningsnapin:prechatAPI that is needed to trigger the chat once the info are filled in.

<aura:component
    implements="lightningsnapin:prechatUI"
    controller="Bot_PreChatCmpCnt">
     
    <aura:attribute name="userId" access="PRIVATE" type="string" default="-"/>
    <aura:attribute name="firstName" access="PRIVATE" type="string" />
    <aura:attribute name="lastName" access="PRIVATE" type="string" />
    <aura:attribute name="email" access="PRIVATE" type="string" />
 
    <!-- Contains methods for getting pre-chat fields, starting a chat, and validating fields -->
    <lightningsnapin:prechatAPI aura:id="prechatAPI"/>
     
 
    <!-- After this component has rendered, call the controller's onRender function -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
     
    <aura:renderIf isTrue="{!empty(v.userId)}">
        <lightning:input type="text" value="{!v.firstName}" label="Name *">
        <lightning:input type="text" value="{!v.lastName}" label="Lastname *">
        <lightning:input type="text"  value="{!v.email}" label="Email *">
         
        <lightning:button label="Start chat!" onclick="{!c.onStartButtonClick}"/>
    </aura:renderIf>
</aura:component>

The list of input fields are only shown when the v.userId attribute is blank (you can note that it is initialized with “-“, and in the lightning controller is blanked only when no logged user is found).

prechatController.js

The controller calls the Apex controller to get the main user info: if they are found, the chat is started.

({
doInit: function(component, event, helper) {
        var action = component.get("c.getCurrentUser");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = JSON.parse(response.getReturnValue());
                console.log(result, embedded_svc);
                component.set('v.userId', result.userId);
                if(result.userId){
                    component.set('v.firstName', result.firstName);
                    component.set('v.lastName', result.lastName);
                    component.set('v.email', result.email);
                    helper.startChat(component, event, helper);
                }
            }else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " +
                                 errors[0].message);
                    }
                } else {
                    console.log("Unknown error");
                }
            }
        });
        $A.enqueueAction(action);
    },
    onStartButtonClick: function(component, event, helper) {
        //handling errors
        if(!component.get('v.firstName')
          || !component.get('v.lastName')
           || !component.get('v.email')) return alert('Missing fields.');
        helper.startChat(component, event, helper);
    }
});

prechatHelper.js

The startChat() method compiles the array of fields to be passed to the chat plugin, that will start the chat with the Bot.

({
     
    startChat: function(component, event, helper){
        var fields = [
            {
                label: 'FirstName',
                name: 'FirstName',
                value: component.get('v.firstName')
            } ,
            {
                label: 'LastName',
                name: 'LastName',
                value: component.get('v.lastName')
            }  ,
            {
                label: 'Email',
                name: 'Email',
                value: component.get('v.email')
            },{
                label: 'Username',
                name: 'Username__c',
                value: component.get('v.userId'),
            }
        ];
        if(component.find("prechatAPI").validateFields(fields).valid) {
            component.find("prechatAPI").startChat(fields);
        }
    }
});

prechatHelper.js

The Apex controller simply makes a query on the user object and considers it a loggedin user if the ContactId field is not null (but you can use your own conditions):

public class Bot_PreChatCmpCnt {
    @auraenabled
    public static String getCurrentUser(){
        Map<String,Object> output = new Map<String,Object>();
        User u = [Select Username, FirstName, LastName, Email, contactId From User Where Id = :UserInfo.getUserId()];
        if(u.ContactId != null){
            output.put('userId', u.UserName);
            output.put('firstName', u.FirstName);
            output.put('lastName', u.LastName);
            output.put('email', u.Email);
        }else{
            output.put('userId', '');
        }
        return JSON.serialize(output);
    }
}

That said we need to instruct the Pre-Chat plugin to write the fields on the LiveChatTranscript object, which is the only thing that grants the Bot’s dialogs to be aware of the running context. Create a new Static Resource and remember to set the Cache Control to Public.

embedded_svc.snippetSettingsFile.extraPrechatFormDetails = [
  { 
    "label":"Username", "transcriptFields":[ "Username__c" ],
  },{
    "label":"Cognome", "transcriptFields": ["LastName__c"]
  },{
   "label":"Nome", "transcriptFields": ["FirstName__c"]
  },{
   "label":"Email", "transcriptFields": ["Email__c"]
}];

This Static Resource must be configured in the Snap-in Component on the Community builder:

Einstein Bot Dialog Apex action

Last step, before configuring the bot, is to create a new Apex Class that will retrieve the users information coming from the current transcript:

public without sharing class Bot_GetSnapInsPreChatData {
    public class PrechatOutput{
        @InvocableVariable
        public String sFirstName;
        @InvocableVariable
        public String sLastName;
        @InvocableVariable
        public String sEmail;
        @InvocableVariable
        public String sContactID;
        @InvocableVariable
        public String sLoggedUser;
    }
    public class PrechatInput{
        @InvocableVariable
        public String sChatKey;
    }
    @InvocableMethod(label='Get SnapIns Prechat Data')
    public static List<PrechatOutput> getSnapInsPrechatData(List<PrechatInput> inputParameters)
    {
        System.debug('######## Input Parameters: '+inputParameters);
         
        String sChatKey = inputParameters[0].sChatKey;
        String sContactId = null;
        List outputParameters = new List();
        PrechatOutput outputParameter = new PrechatOutput();
        if (sChatKey != null && sChatKey != '')
        {
            List<LiveChatTranscript> transcripts = [SELECT Id, CaseId,
                                                    ContactId, Username__c
                                                    FROM LiveChatTranscript WHERE ChatKey = :sChatKey];
            if (transcripts.size()>0)
            {
                sContactId = transcripts[0].ContactId;
                outputParameter.sLoggedUser = transcripts[0].Username__c;
            }
        }
         
        if (sContactId != null && sContactId != '')
        {
            List<Contact> contacts = [SELECT Id, FirstName, LastName, Email, Username__c
                                      FROM Contact WHERE Id = :sContactId];
            if (contacts.size()>0)
            {
                outputParameter.sFirstName = contacts[0].FirstName;
                outputParameter.sLastName = contacts[0].LastName;
                outputParameter.sEmail = contacts[0].Email;
                outputParameter.sContactId = contacts[0].Id;
            }
        }
        outputParameters.add(outputParameter);
        return outputParameters;
    }
}

This class read the coming sChatKey value to query the LiveChatTranscript object that stores all the informations coming from the PreChat.

This LiveChatTranscript can be further manipulated to add more and more data for your context.

You must also define a hidden Bot variable containing the Live chat transcript key, that must be called LiveAgentSessionId (and is populated by the Live Agent engine automatically):

Now you can safely configure your dialog and be sure to know if the user is logged or not, and change the Bot behavior consequently:

[Salesforce] Top Winter19 Platform Release features

 

While the Winter ’19 Salesforce platform release rolls out,I want to introduce to you all Priscilla Sharon, Salesforce Business Solution Executive for DemandBlue, who will share with us here top Winter 19 release features.

DemandBlue is in the business of helping its customers maximize their Salesforce investment through predictable outcomes. As we thrive in an era of cloud-based Infrastructure, Platform and Software services, DemandBlue has pioneered “Service-as-a-Service” through a value-based On Demand Service model that drives bottom-line results. They foster innovation through “Continuous Engagement and On Demand Execution” that offers their customers Speed, Value and Success to achieve their current and future business objectives.

Their On Demand Services for Salesforce include Advisory, Development & Customization, Integration, Administration & Support, Maintenance, and Lightning Migrations.


It’s been a busy month for Salesforce. With the most awaited, world’s greatest tech conference, Dreamforce 2018 unveiling today and the launch of Winter ’19 Release, we are excited to bring you some of most amazing Salesforce Winter ’19 features that enable you to work faster and smarter with more Lightning features, Einstein Intelligence and a whole lore more.

Go on and take a sneak peek into our Top 12 most favorite Salesforce Winter ’19 Release features.

Also, check out the Salesforce Winter ’19 Release notes here.

Change Your View with Display Density Settings (Lightning)

This is one of most useful Salesforce Winter ’19 Features – Two new Lightning Experience display density settings give you more control of how you want to view data without changing the page layout. Select one of the settings as the default, but users can choose their own display density at any time from the user profile menu.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_lex_display_density.htm

Compact

Comfy

Say Goodbye to Copy and Paste and Hello to Quick Text (Lightning)

Copying and pasting content is time consuming and tedious. But now, you can say goodbye to Copy/paste with the newest Salesforce Winter ’19 features. Quick text is fast and easy—you can insert predefined messages into emails, tasks, events, chats, and more. To make quick text easier to use, we added more ways to insert quick text. Use a keyboard shortcut, a button in rich-text editor toolbars, like for email publishers, or a popup button next to supported text fields.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_general_quicktext_buttons.htm

Assign a New Owner to Multiple Leads, Cases, or Custom Objects at One Time (Lightning)

The Salesforce Winter ’19 Features enable you to use the Change Owner page-level button to assign a new owner for up to 200 selected leads, cases, or custom objects. You can access the button in the page-level action menu in a list view or related list in standard table mode, or in Related List Quick Links.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_lex_change_owner.htm

Recover Your Unsaved Text After Getting Timed Out (Lightning, App)

Sometimes your Lightning Experience session is interrupted, whether you’ve been inactive too long or you lost your connection. You used to see the same timeout message, regardless of how your session ended. Now, with the Salesforce Winter ’19 Features, the message that pops up is specific to your scenario and tells you how to recover unsaved text.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_lex_invalid_session_messages.htm

Find the Data You Need in a Jiffy with List View Search (Lightning)

Use the new search bar to search the field data in your list views and find the records you need in record time with the newest Salesforce Winter ’19 features.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_lex_search_lists.htm

Collaborate with Ease with List View Sharing (Lightning)

Have a list view with an amazing set of filters that you’d love to share with your team? Or maybe you have a list view that you only want a select few to access. The Salesforce Winter ’19 features allow you to take collaboration to the next level by sharing your list views with user groups in your org.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_lex_share_lists.htm

Add and Remove Meeting Participants from Any User Interface (Classic)

Attendees (in Lightning Experience) and invitees (in Salesforce Classic) are linked to the same data, so updating those fields should be simple. Now with the Salesforce Winter ’19 features, when you set up sales reps to work with attendees from Lightning Experience and the Salesforce app, they don’t lose access to edit invitees from Salesforce Classic.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_sales_productivity_edit_attendees_anywhere.htm

Send and Receive Images and File Attachments with SMS Text Messaging and Facebook Messenger (Lightning)

They say that a picture is worth a thousand words. The Salesforce Winter ’19 features allow Agents and customers to get straight to the point by sending images and files in an SMS message and Facebook Messenger.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_livemessage_send_and_receive_images.htm

Support Your Customers on YouTube (Lightning, Classic)

One of most amazing Salesforce Winter ’19 Release features is that you can now deliver service to your customers by turning their YouTube comments into cases in Salesforce. Connect your YouTube channel directly to Service Cloud, track cases, and respond directly to customers.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_scs_youtube.htm

Use Joined Reports as Source Reports for Dashboard Components (Lightning)

With a joined report as its source report, a dashboard component can contain data from multiple standard or custom report types. Or, you can provide multiple views of the same object using the Salesforce Winter ’19 features.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_rd_dashboards_source_joined_reports.htm

Give Supervisors a Sneak Peek into What Agents and Customers Are Typing in Chats (Lightning)

The Salesforce Winter ’19 features help supervisors stay on top of messages sent between agents and customers. Supervisors can see what an agent is typing before sending a message with the agent sneak peek feature. Customer sneak peek lets a supervisor see what customers are typing before they hit send.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_omnichannel_supervisor_sneak_peek.htm?edition=&impact=

Explore Data from Multiple Datasets in a Single Lens (Einstein Analytics – Lightning, Classic)

Sometimes the data you want to explore and visualize reside in different datasets. Don’t let that stop you from drilling into your data. With the Salesforce Winter ’19 features, you can now combine multiple datasets in a lens and discover insights about your business faster.

Ref.: https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_bi_explorer_multiple_datasets.htm?edition=&impact=

To learn more about how you can take immediate advantage of the newest features and innovations, talk to our team!
What are your favorite Salesforce Winter ’19 Release features? Please feel free to share your thoughts in the comments section below.

[Salesforce DX / Data Fractory] Populate your Salesforce org with data using Forceea and Salesforce CLI: a step-by-step guide

 
Today’s post has been written by Nikos Mitrakis, the creator of Forceea, an amazing Data Factory Framework for Salesforce.

Some facts about Nikos:

  • Salesforce Developer at Johnson & Johnson EMEA Development Centre (EDC)
  • Started his Salesforce journey in 2014
  • Has passed 9 certifications, including Certified Application Architect
  • Holds a Physics degree
  • Leader of Limerick, Ireland Developer Group
  • Married since 1994, has a daughter
  • Loves watching sci-fi movies and good comedies
  • Lives in Limerick, Ireland

All posts by Nikos


So, you are an awesome Administrator, Developer, Consultant or Architect and you have your Scratch org, Developer Sandbox or Developer edition org ready for development, testing, training or a demo. But your org doesn’t have any data ☹, or it doesn’t have the data you want. What can you do?

Well, you have the following options:

  1. Use an ETL tool to move data from another Org or get data from CSV files.
  2. Use Salesforce CLI (Command Line Interface) using the commands sfdx force:data:tree:export and force:data:tree:import to export/ data from another Org and import the data (in JSON format).
  3. Develop a custom solution (Apex) to insert the records you need programmatically.
  4. Use a Data Factory to insert the required data.

The first (ETL) and second (CLI) solutions don’t need development skills, they may not be very difficult to configure (using CLI should be easier), and they let you populate your org with a specific set of records – if you really want this. The problem is that data requirements change very fast and if you have to continuously create manually the records you need in one org and then copy them to your org, this process will eventually be slow and time-consuming.

The third (Apex) solution gives you the maximum flexibility, but it’s time-consuming as well, not to mention the high level of technical knowledge it requires.

Now let’s see the fourth solution, the Data Factory. Using a Data Factory, you won’t have to write complex code or have advanced knowledge of an ETL tool. You’ll be able to easily generate and insert the records you need for any SObject and easily modify the process to adopt any new data requirements. Sounds interesting?

Stay with me as we’re going to implement such a data population project using Forceea (forˈsēa) data factory framework – this framework is an open source GitHub project (https://github.com/nmitrakis/Forceea). Keep in mind that the framework is perfect for a developer who wants to create records for the test methods, but that’s another story.

In this step-by-step guide we’ll assume that you have no programming knowledge! (you may be even a power Salesforce user). Ready to start? (Take a deep breath…)

Step 0: Prerequisites – Prepare your org

  • For Classic orgs: You have created a Sandbox or a Developer org.
  • For Salesforce DX Scratch orgs: you have created your scratch org.

For both Classic and DX, after the org creation you should have deployed your project’s metadata and set your org ready for the final data population.

Step 1: Install the Salesforce CLI

If you haven’t installed the Salesforce CLI, go to https://developer.salesforce.com/tools/sfdxcli, download the CLI for your system and install it. Accept the default settings and after a while your Salesforce CLI will be ready to run.

Step 2: Authorize your org

To use CLI, you need to authorize your org. To do this, open the Command Prompt window and execute the following command:

sfdx force:auth:web:login -r https://login.salesforce.com -a OrgAlias

Some comments here:

  • If you’re authorizing a sandbox, the instance URL will be https://test.salesforce.com.
  • You should replace OrgAlias with the alias of your org (choose one, e.g. sf1).

To verify that everything is fine, log into your org using the command

sfdx force:org:open -u OrgAlias

Step 3: Install Forceea

There are two ways to install Forceea.

Method 1: Go to https://github.com/nmitrakis/Forceea and click the following button:

You’ll be re-directed to the page:

  • If you install in a sandbox, select Deploy to: Sandbox. Otherwise, accept the default selection (Production/Developer).
  • Click the Login to Salesforce button (on the right corner) and give your credentials.
  • Then click Allow to give the tool the access to your org. You are redirected to a new page where the From GitHub Repository section lists the details of Forceea URL and the To Salesforce Org section the details of the target org. Click the Deploy button (on the right corner).
  • After a few seconds you’ll see the message Deployment Complete at the bottom of your page.

Method 2: Go to the GitHub repository https://github.com/nmitrakis/Forceea and click Clone or Download.

Click Download ZIP. After a few seconds the Forceea-master.zip will have been downloaded. Unzip the zip file and you will find the metadata folder, which contains

  • the src folder, with a folder with each metadata component and the package.xml
  • the dx folder, with the Salesforce DX components
  • a build.properties file
  • a build.xml file

The easiest way to regularly use Forceea is to include its metadata into your Repository (either classic or DX metadata). Then you can deploy it with your project’s metadata.

Step 4: Create the Forceea scripts

What are Forceea scripts?

Forceea uses a language (Sample Data Definition Language – SDDL) to describe the “nature” of the required data. A script is a set of commands. Let’s see an example, which creates and inserts opportunities:

FObject obj = new FObject('Opportunity', 100);
obj.setDefinition('Name', 'static value(Opp-)');
obj.setDefinition('Name', 'serial type(number) from(1) step(1) scale(0)');
obj.setDefinition('AccountId', 'random lookup(Account) field(Industry) value(Chemicals,Construction) source(salesforce)');
obj.setDefinition('Amount', 'random type(number) from(1000000) to(10000000) scale(-3)');
obj.setDefinition('StageName', 'random type(picklist)');
obj.setDefinition('CloseDate', 'random type(date) from(2017-01-01) to(2017-12-31)');
obj.setDefinition('Forceea__c', 'static value(xJio9!23)'); // ** create this field **
obj.insertRecords(true);

If the above commands look like Apex statements, you’re right, they are Apex statements, but you may forget it for the moment! The above script will insert 100 Opportunity records with:

  • Name: Opp-1, Opp-2, .., Opp-100
  • Account: any account for which the Industry is “Chemicals” or “Construction”
  • Amount: a random integer from 1M to 10M, round to 1000 (e.g. 9,252,000)
  • Stage: any picklist value
  • Close date: any date from 1 Jan. 2017 to 31 Dec. 2017

A field definition begins with obj.setDefinition and has two text parameters:

  • The field API name, e.g. Amount or AccountId
  • The SDDL definition, e.g. random type(number) from(1000000) to(10000000) scale(-3) or random type(picklist).

Finally, we insert the created records using obj.insertRecords(true). The parameter true means that it is all or nothing, so if any error happens, no records will be inserted.

The framework has many cool features:

  • Creates records for standard or custom objects, for any standard or custom field.
  • Automatically defines required fields.
  • Can create data for fields of every data type: Integer, Currency, Double, Date, Datetime, Time, Boolean,
    String, TextArea, Percent, Reference, Email, Phone, URL, Base64, Picklist and MultiPicklist.
  • Handles record types and field dependencies (dependent picklists).
  • Supports record groups for inserting and deleting records.
  • Validates the definitions based on the field data type.
  • Can be used for in test methods or for populating Salesforce orgs with sample data for demos and User
    Acceptance Testing (UAT).
  • Has an extended error messaging system.
  • You can get a lot of script examples from http://bit.ly/Forceea131_Examples and download the User Guide from http://bit.ly/Forceea131_UserGuide.

    Write your own scripts

    Now you know what is a Forceea script, let’s see how you can write the scripts for your specific needs. To do this, use the following template:

    FObject obj = new FObject('SObject_API_Name', Number_of_records);
    FObject.seed = 1;
    <field definitions>
    obj.insertRecords(true);
    

    where are one or more SDDL field definitions, like the previous definitions we used to create a script for Opportunity records.

    The seed is very important when you want to create the same random records every time. For example, when you populate a Scratch org with sample data, we may want each developer to have the same (but random) set of records. Forceea uses its own engine to create random data (generally called Pseudo-random Number generator – PRNG), which you can control.

    Now, let’s suppose you want to populate your org with Account and Opportunity records. This means that first you must create records for accounts and then for opportunities (an opportunity is related to an account, that’s why we insert accounts first).

    Accounts

    Open your favourite text editor (I use VSCode) and create a script using the above template. Your script may look like:

    FObject obj = new FObject('Account', 100);
    FObject.seed = 1;
    obj.setDefinition('RecordTypeId', 'static value(BigAccount)');
    obj.setDefinition('Name', 'static value("Company ")');
    obj.setDefinition('Name', 'serial type(number) from(100) step(1) scale(0)');
    obj.setDefinition('NumberOfEmployees', 'random type(number) from(10) to(1000) scale(-1)');
    obj.setDefinition('AnnualRevenue', 'random type(number) from(10000000) to(100000000) scale(3)');
    obj.setDefinition('Rating', 'random type(picklist) except(Hot)');
    obj.setDefinition('Phone', 'random type(phone) format("(30) 210 dD-00-DD")');
    obj.setDefinition('Industry', 'random type(picklist)');
    obj.setDefinition('Type', 'random type(list) value(Prospect, Customer - Direct, Customer - Channel)');
    obj.setDefinition('Site', 'random type(url)');
    obj.setDefinition('ShippingStreet', 'random type(street) group(shipping)');
    obj.setDefinition('ShippingPostalCode', 'random type(postalcode) group(shipping)');
    obj.setDefinition('ShippingCity', 'random type(city) group(shipping)');
    obj.setDefinition('ShippingState', 'random type(state) group(shipping)');
    obj.setDefinition('ShippingCountry', 'random type(country) group(shipping)');
    obj.insertRecords(true);
    

    Even though we don’t have the space here to describe every SDDL definition of the above script, I’d like to mention the first field definition for field RecordTypeId (if you use record types, modify the definition with the API name of your record type instead of BigAccount, otherwise delete this line) and the address definitions ShippingStreet, ShippingPostalCode, etc (where you get real addresses from United States).

    You may think that these definitions are difficult, but most of them are obvious and easy to understand. So, back to our script for the Account SObject, give it the name Accounts.apex and save it into your preferred folder (let’s call it ForceeaScripts).

    Opportunities

    Now it’s time to create the Opportunities.apex file with the script for the Opportunity SObject. Follow the previous procedure and write a script like the example I gave you above.

    Keep in mind that Forceea will try to automatically find the required fields and generate a field definition for them but, as a rule of thumb, you should always create your definitions for all required fields.

    Record Deletion

    When you create records, you probably want to repeat this procedure again, and replace the existing set of data with another set with different or the same field values. To do this, you probably want to delete the existing inserted records before you insert the new ones. This is the responsibility of the Record Deletion files.

    First, we’ll delete the opportunities we created. Follow these steps to configure it:

    • Create a new text file, call it delete-opportunities.apex and save it in the ForceeaScripts folder.
    • Write this script in the file:

      String flag = 'xJio9!23';
      List<Opportunity> records = [SELECT Id FROM Opportunity WHERE Forceea__c = :flag LIMIT 5000];
      delete records;
      

    You’re right! At first sight these commands may look difficult if you are not a developer, but they aren’t really hard to understand if you follow these instructions:

    • Line 1: You may select your own (random) value, like xJio9!23 – but don’t forget to enclose it in single quotation marks
    • Line 2: Find a filed you don’t use, which has a Text data type or create your own text field and call it Forceea__c. Here I use the latter, because I couldn’t find any available (not used) standard field on the Opportunity SObject.

    Now go to the opportunities.apex file and add the following line before the command obj.insertRecords(true); :

    obj.setDefinition(Forceea__c', 'static value(xJio9!23)');

    As you can see, we set the field definition for the field Forceea to be our static value xJio9!23. Do the same for the Account SObject, creating the file delete-accounts.apex with the following commands:

    String flag = 'xJio9!23';
    List<Account> records = [SELECT Id FROM Account WHERE Tradestyle = :flag LIMIT 5000];
    delete records;
    

    In Line 2, I suppose the TradeStyle text field is not used in your org, so you may use it here. Else, you should create a new field as previously.

    Go to the accounts.apex file and add the following line before the command obj.insertRecords(true); :

    obj.setDefinition('TradeStyle', 'static value(xJio9!23)');

    Be careful! The above scripts will delete up to 5,000 records, so if you have more records you have 2 options:

    • Increase LIMIT 5000 up to 10000 (e.g. LIMIT 8000)
    • Execute the delete-accounts.apex again (you may use it as many times as you want)

    That’s it! Now you have 4 files into your ForceeaScript folder:

    • account.apex
    • opportunities.apex
    • delete-accounts.apex
    • delete-opportunities.apex

    For your convenience, I have created these files in a zipped file, which you can download from http://bit.ly/ForceeaWithCLI.

    You may use these files for your training. I suppose you should modify them if you want to use them in a production system (with specific requirements for the field values), but you’ll probably need no modifications if you execute them in an out-of-the-box Developer/Scratch org.

    Step 5: Execute your scripts

    The last step is to execute the scripts and insert the created records. Create a new text file, call it execute-scripts.bat and save it in the ForceeaScripts folder (I included it in the above zipped file).

    In this file you’re going to insert the CLI commands which execute the *.apex files you created previously.

    If you use Windows, your execute-scripts.bat file will look like:

    sfdx force:apex:execute -f .\delete-opportunities.apex -u OrgAlias
    sfdx force:apex:execute -f .\delete-accounts.apex -u OrgAlias
    sfdx force:apex:execute -f .\accounts.apex -u OrgAlias
    sfdx force:apex:execute -f .\opportunities.apex -u OrgAlias

    where orgAlias is the alias for your org you defined in Step 2.

    If you’re using a Mac, each command may look like:

    sfdx force:apex:execute -f /Users/Username/Documents/ForceeaScripts/accounts.apex -u OrgAlias

    When you write your Forceea scripts (e.g. your script in the accounts.apex file), you may have errors to correct. For example, you may have misspelled a field’s API name or your SDDL definition may have a syntax error (a very common source of errors is the effect of the Validation Rules and Triggers). Fortunately, the framework has an extensive debug log, with detailed error messages (see the User Guide, pages 44 – 50). You can activate these debug logs, if you insert the command obj.setVerbose(‘info’) or obj.setVerbose(‘debug’) after the first command of your accounts.apex or opportunities.apex script files.

    I suggest you initially execute your script files one by one.

    • If you already have inserted records, first execute the two delete-object files. Copy the “delete” commands from your execute-scripts.bat to your Command Prompt window and execute them. Then verify that records have been deleted successfully.
    • Copy the “insert” commands from your execute-scripts.bat file to your Command Prompt window and execute them one by one, verifying that records have been inserted successfully.
    • When you have verified that everything works as expected, you may just execute your batch file in the Command Prompt window: > execute-scripts.bat (Window users)

    If you are a Mac user, you could use a similar batch execution or just simply copy all commands of the execute-scripts file to the Command Prompt window and execute them at once.

    Because of this process, all lines of the execute-scripts file will be executed sequentially, each on its separate execution context. This is very important, since it will allow each sfdx force:apex:execute command to be executed on its own Governor Limits.

    Optional Step 6: Execute multiple scripts for the same SObject

    You may ask: Why create multiple script files for the same SObject? Well, we just mentioned that each script file (*.apex) is executed by the Salesforce CLI having its own limits. There are a lot of limits, but when you insert records you’re going to hate a limit called “Maximum CPU time on the Salesforce servers”, which is 10,000 ms (that is 10 seconds). In practise this limit may not allow you to insert more than 200 records in a complex implementation (with triggers, many validation rules and so on) or even no more than 50 records!

    So, let’s suppose that you try to insert 2,000 opportunities but the insertion fails because of this limit. What is the process you should follow?

    1. Try to execute the script file (sfdx force:apex:execute -f .\opportunities.apex -u OrgAlias) using 100 records, i.e. FObject(‘Opportunity’, 100)
    2. If your execution is successful, double the records (200), if not set the number of records to half (50).
    3. Follow the same logic, increasing or decreasing the number of records, to find an optimal maximum value. Take into consideration that Salesforce doesn’t always need the same time to execute your script, so it’s better to set a value less than the absolute maximum.

    For example, suppose that you find you can insert up to 250 records. It’s safer to decrease this by 10% and set 225 records.

    • Because you want to insert 2,000 records, but each script file will insert 225 records, you need to create 9 script files. The first 8 files will insert 225 records each and the last one will insert 200 records (225 * 8 + 200 = 2,000 records).
    • The second line of each script file contains the seed number (FObject.seed = …). Here we have something new: we’re going to use different seed numbers for the same SObject. You may use whatever numbers you want or something like 1,2,3, etc. So, the first file will have FObject.seed = 1, the second FObject.seed = 2, etc. Why do we set different seed values? If we don’t, Forceea will create the same (but random) values in each execution for this SObject (same Close dates, same Amounts, etc), something we don’t want at all! Of course, you may omit the seed command if you don’t want to have the same values whenever you execute your scripts.
    • Another important note is this: if you use seed numbers you should always delete the previously created records, unless the same seed number is never used again. For example, if you insert the 2,000 records using seeds from 1 to 9, if you insert new records using a seed between 1 and 9, these new records will be the same as some already created records (something BAD). So, you must use a new seed number (e.g. 10) or delete the records you inserted before inserting new ones.
    • Each script file may have the same or different field definitions. It’s up to you to decide what kind of data you want.
    • And a last tip: if any of your definitions uses the serial command (e.g. serial type(number) … in the Opportunity.apex), first insert the command obj.createRecords(numberOfNextrecord); before the final line obj.insertRecords(true); where numberOfNextrecord is the number of the next record to be inserted. For example, in the first script file it will be createRecords(1), in the second createRecords(101), in the third createRecords(201), etc – under the assumption that you insert 100 records in each script file. If you follow this tip, all inserted records will have a continuous serial number!

    Conclusion

    Congratulations! You finally managed to reach at the end of this step-by-step guide. I hope I convinced you that Forceea with Salesforce CLI will make your life much easier. After you create the set of your script files, you can automate the creation of all your SObjects using a unique batch file. CLI will execute your batch files line by line, creating and inserting your records, with each execution with new Limits (which is fantastic!!)

    It will be great to have your feedback after your try to create a few scripts in a Sandbox or Developer org. And don’t hesitate to send an email with any questions or issues you may have.

Page 10 of 26

Powered by WordPress & Theme by Anders Norén