Thursday, May 26, 2016

Salesforce: Multi-Person Calendar Event (User as invitee)

In previous blog Multi-Person Calendar Event (Contact / Lead as invitee), we discussed about adding contact or lead as invitee, we also discussed the structure at the backend and how we can use API to add contact or lead as invitee.

But, when the invitee is a user, the structure will be a little different, although the objects used is the same.

1. Event object
Instead of create only 1 event record as add contact/lead as invitee, invite user will create multiple event record based on number of invitee + sender. In this scenario, we are going to invite 2 users and 1 contact.

Sample query: Select Id, Subject, OwnerId, GroupEventType, IsChild, WhatId, WhoId, CreatedDate, ActivityDate, ActivityDateTime, StartDateTime, EndDateTime, EventSubtype, IsReminderSet, Type, WhatCount, WhoCount FROM Event WHERE Subject = 'Test with User'

This will create 3 events with same subject, one event for each User, but only 1 with IsChild = False, which is "parent" event. Also notice that each record have different Owner Id, and all events with GroupEventType = 1, remember that we cannot populate / update GroupEventType manually.

2. EventRelation object
Sample query: SELECT Id,EventId,RelationId,IsParent,IsWhat,IsInvitee,Status,CreatedDate FROM EventRelation WHERE EventId IN ('00U63000001T8Y9EAK','00U63000001T8YAEA0','00U63000001T8YBEA0')

Notice that records created in this object is relate to: 1 opportunity, 1 contact and 2 users, but all linked to the same event, which is parent event where IsChild = False.

3. EventWhoRelation object
Same with EventRelation object, only 1 record created as we only have 1 contact relate to the event, and it is linked to the parent Event (IsChild = False)

Sample query: SELECT Id, EventId, RelationId, Type, CreatedDate FROM EventWhoRelation WHERE EventId IN ('00U63000001T8Y9EAK','00U63000001T8YAEA0','00U63000001T8YBEA0')

How to auto add User as Invitee Event with API?

You just need to insert record(s) to EventRelation object, 1 record for 1 contact / lead. Here are fields you need to populate:
1. EventId = Event Id
2. RelationId = User Id
3. IsParent = False
4. IsWhat    = False
5. IsInvitee = True
6. Status   = New

This is similar with add Contact / Lead as invitee, the difference is: Salesforce will auto create event record for the user as child record, if the parent record initially is not for multi-person, GroupEventType will change from 0 to 1.

Salesforce: Multi-Person Calendar Event (Contact / Lead as invitee)

In Salesforce, you can create event and relate to multiple Contacts (up to 50 contacts), but make sure you have enable Allow Users to Relate Multiple Contacts to Tasks and Events from Setup | Customize | Activities | Activity Settings.

You also can invite Contacts that is not defined in the Relate To for the event, including from Leads.

As you see from screenshot above, the event is relate to Opportunity and 2 contacts, we add both Contacts as invitee, and then we also add 2 Leads as Invitee.

So what happened in the backend ?

1. Event object
Salesforce create a new event record, because this is Multi-Person Calendar Event, notice GroupEventType = 1; while WhoId is the primary Contact.

Note that you cannot populate GroupEventType from API, but the value will be auto populate based on event category:
  • 0 (Non–group event)—An event with no invitees.
  • 1 (Group event)—An event with invitees.
  • 2 (Proposed event)—An event created when a user requests a meeting with a contact, lead, or person account using the Salesforce user interface.  

Sample query: Select Id, CreatedDate, ActivityDate, ActivityDateTime, ReminderDateTime, StartDateTime, EndDateTime, EventSubtype, GroupEventType, IsReminderSet, OwnerId, Subject, Type, WhatCount, WhatId, WhoCount, WhoId FROM Event WHERE Id = '00U63000001T8XGEA0'

2. EventRelation object
Represents people (a user, a lead, or contacts) or a resource (such as a conference room) invited to an event.  For above screenshot scenario, query to this object for above event will return 5 records: 2 Contacts, 2 Leads and 1 Opportunity.

Sample query: SELECT Id, EventId, RelationId, IsParent, IsWhat, IsInvitee, Status, CreatedDate FROM EventRelation WHERE EventId = '00U63000001T8XGEA0'

3. EventWhoRelation object
Represents the relationship between an event and a lead or contacts, this object DO NOT have relation with invitee, but it is pure on contacts or lead Relate To the Event. EventWhoRelation allows a variable number of relationships: one lead or up to 50 contacts. Available only if you’ve enabled Shared Activities for your organization.

Sample query: SELECT Id, EventId, RelationId, Type, CreatedDate FROM EventWhoRelation WHERE EventId = '00U63000001T8XGEA0'

From the top screenshot scenario, query will return 2 records which is Contact relate to: Mike Lee and Jack Man. We cannot create record directly in EventWhoRelation object with API.

How to auto add Contact / Lead as Invitee Event with API?

You just need to insert record(s) to EventRelation object, 1 record for 1 contact / lead. Here are fields you need to populate:
1. EventId = Event Id
2. RelationId = Contact Id / Lead Id
3. IsParent = False
4. IsWhat    = False
5. IsInvitee = True
6. Status         = New


Wednesday, May 25, 2016

Salesforce: Automate Assigning Managed Package Licenses

When you purchase 3rd party app by License (from AppExchange or others), once installed in Production, you will find the Packaged in Setup | Installed Packages. For free package, it will be available for all users, but for license by user, you will notice Manage Licenses link next to the Package Name. Then admin or user with Manage Package Licenses permission need to add users for particular license. This is simple job, but when you have new user onboard and offboard over the times, this activity often forget and become not practical.

Can we automate this? 
Since Summer 14 release, Salesforce make the object available via API, where you can use Process Builder + Flow or Trigger to automate license assignment and license removal.

There are 2 object you need to work with:

1. PackageLicense
Represents a license for an installed managed package.
This object only support record query, not create, update, and delete.

2. UserPackageLicense
Represents a license for an installed managed package, assigned to a specific user.
This object support record create, delete, query, but not update.

I'll not go down to the detail on how to create Process Builder + Flow or Trigger code in this blog, but the idea is based on objects above, you need to get the PackageLicense Id, the create new record in UserPackageLicense, you just need to provide PackageLicenseId and UserId.

Sample Query
SELECT Id, NamespacePrefix, AllowedLicenses, UsedLicenses FROM PackageLicense WHERE Status = 'Active' AND AllowedLicenses > 0 ORDER BY NamespacePrefix

SELECT Id, PackageLicenseId, UserId FROM UserPackageLicense WHERE PackageLicenseId = '050o0000000DC8JAAW'


Sunday, May 22, 2016

Salesforce: New Event versus New Meeting Request

In previous blog, we discussed about New Meeting Request. However, using Event and Select Invitee, this will also can be used to send invite for coworkers and customers.

What is similar between New Event with select Invitee versus New Meeting Request?
  • Both can be launch from Home page calendar and Open Activities of lead and contact.
  • When you can use customize logo in meeting request, it will be the same logo for both, you can configure from Setup | Customize | Activities | Activities Setting | Show Custom Logo in Meeting Requests
  • Both can invite User, Lead, and Contact
  • Both have start and end date time
  • Both have Location and Subject
  • Invitees will get email of the invite, although the message a little different, Meeting Request have more content, see screenshots below
  • Invitees to response the invite
  • Both event is report-able using standard report type = Events with Invitees

New Event with select Invitee

New Meeting Request

What is the difference between New Event & New Meeting Request?
An event does not necessarily mean that you will be having a meeting with someone, even the event type is meeting, your customer will not receive meeting invite, until you add them as Invitee. When you create new event, scroll down to the bottom and look for Select Invitees section

Once you add invitee to the event, notice the event title change from New Event to New Multi-Person Calendar Event, and there is a button Save & Send Update, this will send email to all invitee. Once New Meeting Request is confirmed, it will have the same behavior as Event with invitee.

New Event 
  • Sender will receive initial email and it consider confirmed invite
  • Meeting times is fixed
  • No customized message 
  • Event send will show in sender Calendar as "Scheduled Meetings"
  • Invitees to accept or decline invite, issue: sender do not get email when invitee response.

New Meeting Request
  • Sender can propose up to five meeting times
  • Sender can customize message
  • When meeting invite sent, event will be show in sender Calendar as "Requested Meetings"
  • Invitees receive email and select preferred meeting times or propose new times
  • After invitee responses, sender to confirm the meeting, sender will get email when invitee response.
  • Invitees will receive email and need to accept or decline confirmed meeting times, here we have the same issue as New Event, sender do not received email as well.
  • When sender confirmed the meeting time, event will move from "Requested Meetings"to "Scheduled Meetings" in Home page

Sample Report
In this scenario, we are using report type "Events with Invitees"
 Sender = Jack Bob
 Invitee 1 = Linda Yie (co-worker)
 Invitee 2 = Sean Lee (lead)

Initial sent
Linda received email
Sean received email

Linda select a time
Nothing change in report

Sean select a time
Nothing change in report

Jack confirm the meeting time
Linda received email
Sean received email

Sean accept & Linda reject the invite

Sender can track who has accept, decline and has not responded to the invite from the event itself.


Salesforce: Cloud Scheduler aka New Meeting Request

Cloud Scheduler allows your users to request meetings with customers and coworkers, and lets customers and coworkers select when they can meet before organizers confirm meeting times. The New Meeting Request button lets users request meetings using Cloud Scheduler. It's added by default in the Home page under Calendar component, and in Open Activities related list for contacts, leads, and person accounts (if enabled).

If you not see New Meeting Request button in the Home page, make sure Calendar component is added to your Home page layout. After that also make sure Show Requested Meetings in the Calendar Section on the Home Tab is selected under Setup | Customize | Activities | Activity Settings. When this is selected, you will see Scheduled Meetings and Requested Meetings tab under Calendar.

"Show Requested Meetings in the Calendar Section on the Home Tab" NOT selected

"Show Requested Meetings in the Calendar Section on the Home Tab" is selected

For New Meeting Request button in Open Activities related list of Lead and Contact, make sure the button New Meeting Request is added to the page layout.

When you use Cloud Scheduler to request a meeting with a contact, a lead, a person account, or a coworker, Salesforce creates a unique Web page for your meeting that displays the proposed meeting times. When invitees visit the page, they select the times that work for them and send you a reply. Salesforce tracks all the responses so that you can pick the best time to meet when you confirm the meeting.

  • You must have at least read access to the contacts, leads, and person accounts that you request a meeting with.
  • Each invitee must have an email address specified in their record so Salesforce can send them a meeting request.
  • You can invite up to 50 people to a meeting. Invitees can consist of only contacts, leads, or person accounts, only coworkers who use Salesforce, or a combination.
  • You can propose up to five meeting times by picking times in the calendar.
  • Recommend you to install Salesforce for Outlook so you can sync your calendar events between Salesforce and Microsoft® Outlook®
  • Your meeting’s Web page displays all messages between you and the invitees. This includes messages that invitees write when responding to your request.
  • If you requested the meeting from an Open Activities related list, the meeting appears on the detail page for that contact or lead only. It doesn’t appear on the Open Activities related list for any other invitee. For example, if you requested a meeting with Jane Smith from her contact detail page and then clicked the To field to invite John Doe, the requested meeting only appears on the Open Activities related list for Jane Smith and not John Doe. If you requested the meeting from the Calendar section on the Home tab, the meeting doesn't appear on the Open Activities related list for either Jane Smith or John Doe.

Currently Meeting Request only available for weekday, vote this idea to include weekend in the meeting request and this idea

Reference: How Cloud Scheduler Works in Salesforce Classic

Thursday, May 19, 2016

Salesforce: Personal Groups

Public Groups is one of the most famous and widely use feature in Salesforce, with contain a set of users, it can be individual users, other groups, the users in a particular role or territory, or the users in a role or territory plus all of the users below that role or territory in the hierarchy.

Only admin (or users with Managed Users permission) can create Public Group. Public Group can be used from sharing rules, manual record sharing, report/dashboard folder sharing, list view visibility and etc.

What is Personal Group? 
Personal group is not so popular compare to Public Group. Personal Group are intended only for the user themselves to create and manually add members.

Salesforce user can create and manage their own personal group from Name | My Settings | Personal | My Groups, from here you click New Group or edit or delete existing group. Each user can create more than 1 personal groups.

While Public Group only for system admin to setup, Personal Group can only be created, edit, "seen" and used by the User himself (no one else can access it).

Personal Group Usage
Once your personal group created, you can use it to share records to this specific group. But, make sure your Salesforce admin to add Sharing button to the page layout.

If there is no personal group created, you will not see Personal Groups option in drop down menu. Before Personal Groups created:

Once Personal Groups created:


Wednesday, May 18, 2016

Salesforce Verification Code

To help protect your organization’s data from unauthorized access, Salesforce by default implement identify verification code. When you login to Salesforce from unknown network, or from new computer / device, or with new browser, or just clean your web browser cache. Salesforce will send you verification code via  mobile SMS or via email, if you do not add mobile number to user user profile.

But, can we skip this verification code? Yes by adding Trusted IP ranges, users in IP ranges can log in without receiving a login challenge for verification of their identity.

Adding trusted IP Ranges (you define a list of IP addresses) to Network Access 
Navigate to Setup | Security Controls | Network Access
This setting will be applicable for the whole users in the org.

Another security measure is to white-list only range of valid IP addresses from which users can log in to Salesforce. User login from IP Addresses not in IP ranges defined will be restricted to access Salesforce. To setup this restriction, navigate to Setup | Manage Users | Profiles - select a profile and scroll down to Login IP Ranges. When user login from this IP ranges, they will not get verification code as well.
This setting will be applicable for all users in the Profile.

In summary:

Network Access (available for all editions)
  • Setting trusted IP ranges under Setup | Security Controls | Network Access opens access to users accessing Salesforce from the trusted IP addresses. Users will not be challenged with the 5-digit verification code to authenticate the IP address from where they are logging in. All the customer apps and integration will not need the security token.
  • These can only be added or removed by a system administrator. Removing them from the Network Access will not revoke access from these IP addresses.

Profile-Based IP Restrictions (Available in Enterprise, Unlimited, Developer)
  • You can set IP Restriction under each profile. This will restrict access, and users will only be able to log in from the IP addresses listed.
  • ​Users will not be able to access Salesforce from any IP that is not listed in the range. They will receive a Restricted IP error when logging in.
  • ​This setting is recommended for organizations with users who log in only using VPN or their public corporate network IP addresses.
  • ​Please make sure that all the IP ranges for your apps and integration are added as well.


Thursday, May 12, 2016

Campaign Member Status & Responded

New campaigns have two default member status values: “Sent” and “Responded”. You can edit them or create new ones.
  • Click Advanced Setup on a campaign detail page.
  • Click Edit.
  • Update the existing entries or add new values.
  • Click Add More as needed to add additional entries. You can add up to 50 entries.
  • Select one entry as the “Default” value.
  • Choose which values will be counted as “Responded.”  Members with “Responded” values are tallied in the Total Responses field on the campaign. Status marked as Responded will cause a field called Responded to True (API Name = HasResponded)

But, you will also notice there is a field in Campaign Member object called Status, and when you click that field, you will see a few values there, and there are no New button to add value.

So, how this work? When user add new Status entry in Campaign detail page, if the Status doesn't exist in field Status in setup, system will auto add the new values, this is totally different with others picklist values.

Modifying the Responded checkbox has broad effects. When you select or deselect the Responded
checkbox, campaign statistics and campaign member details change accordingly. Specifically, the fields Responded, Last Responded Date, and Last Modified change on the campaign member record. For example, if you're working with a status called “Attended” and you select the Responded checkbox for it, existing campaign members whose status is “Attended” will then be counted as responses in campaign statistics and the aforementioned date fields will update.

Reference: Customizing Campaign Setup

Salesforce: View All Campaign Members Report

For those of you who have got an error message when clicking the View All Campaign Members link in a Campaign and get the error message "URL Has Moved".

If you are a Salesforce admin, follow this step to fix it permanently in your org:

1. Navigate to Setup | Customize | Campaign | Buttons, Links, and Actions
2. Click Edit in the View All Campaign Members link
3. Edit the URL from

4. Done

Now, all of your users should get the right report name "Campaign Call Down Report".

Edit Aug 2023, the above step is only applied in Classic, but who is using Classic in 2023?

To get a similar report in Lightning:
  • Create a new report using the "Campaigns with Campaign Members" report type, make sure to store the report in a public folder or other folders that are accessible by your users
  • Set filter: Show all campaigns and filter with a campaign name
  • Note the report URL
  • Add a new custom link in the Campaign object under "Buttons, Links, and Actions"
  • Add a report parameter at the end of the URL, e.g.{!Campaign.Name}
  • Add the custom link to the Campaign page layout and save it

Salesforce: Who add Contact/Lead to Campaign?

In many organizations, Campaign is owned by Marketing, but Contact and Lead is owned by Sales. By default, all users can add Contact/Lead to Campaign as Campaign member.

There are many ways to add Contact/Lead to a Campaign as member, see this blog.

You can run a report with report type 'Campaigns with Campaign Members' to get all the members related to the campaign and other information for that members.

When you run the report, notice 3 important dates:
- Member First Associated Date: when is the member added to Campaign
- Member Status Update Date: when is last status update of the member
- Member First Responded Date: when is the status flip to Responded

But, the report do not have info on who add the Contact/Lead as member, it can be added by sales rep, marketing user, or by someone else.

1. Custom Field
Create a custom formula field with return type = Text.
CreatedBy.FirstName + " " + CreatedBy.LastName
So, just use the custom field to report type 'Campaigns with Campaign Members'.

2. Custom Report Type
Create custom report with Primary object = Campaigns and relate to Campaign Members.
Find Created By: Full Name field in Campaign Members object.
This field will show who is the user who add the Contact/Lead as member.

Page-level ad