Showing posts with label Communities. Show all posts
Showing posts with label Communities. Show all posts

Monday, January 11, 2016

6 Reasons You Got the Generic Error Page

Sometimes in Visualforce, you'll have debug logging enabled for a community or portal user, but loading a page fails with no trace of what went wrong. When you look in the debug log for an explanation, all you see is that Salesforce successfully loaded the Generic Error Page configured for the site.


Before logging a case or asking a fellow developer for help, check for the following 6 common culprits.

  • Are you missing any static resources, {!$Resource.__}?
  • Are you missing any custom labels, {!$Label.__}?
  • Are you missing any custom permissions, {!$Permission.__}?
  • Are you missing any page references, {!$Page.__}?
  • Are you missing any custom controller/extension properties bound on the page? This can be a problem when deploying packages among sandbox orgs.
  • Are you missing any custom controller/extension actions bound on the page?

What I've also discovered, interestingly enough, is that for some reason using MavensMate v6.0.0 with Sublime Text 3, saving a Visualforce page or component skips the validation for global variables used in Visualforce.

Tuesday, May 5, 2015

4 Warning Signs You’re Spamming, Not Sharing

A poll recently appeared about whether sharing blog posts to multiple groups within the Salesforce Success Community constitutes spam. Behind that poll was a lengthy conversation and another poll, where opinions seemed to be split 50-50 between "yes, cross-post freely" and "no, keep it contained in an opt-in channel". So, if I write a piece about best practice for regression testing in Salesforce, and in my excitement I want to share that piece with others on the Success Community, am I sharing or am I spamming? (For the record, the piece I mentioned is hypothetical. I haven't written any such piece to date.)

There's a fine line between sharing for the good of a community and spamming the community in self-promotion (intentional or not). And as a professional consultant, I try very hard to walk that fine line without crossing into spam territory.

The 4 warnings signs below highlight my views on what's spam and what's not.

1. Your post promotes a product or service


When starting a new thread of discussion with a new post, consider whether the content you're sharing mentions a specific paid app from the AppExchange or highlights the success of a specific consulting company. If so, chances are people are going to feel like you're spamming.

I do want to highlight a difference between posting new (unsolicited) instead of responding to a question or an explicitly expressed need (solicited). In the latter case, you could actually be helping by pointing the other person to a solution, paid or otherwise, that really addresses the need.

Consultant's note: Sometimes I come across a question on the community that seems like a lead for a new project at a prospective client. Personally I do still take time to answer the question in as much detail as I think is feasible, so that the poster has enough guidance to either implement the solution on his own or to contract a partner to help. Posting bluntly, "you need a partner to help" would be inappropriate.

2. You blindly cross-post your blog across multiple groups


With Chatter, it's super easy to share a single post across multiple groups, either by sharing (i.e., reposting) the original post or by mentioning other groups in a comment. If you're simply cross-posting without assessing and repackaging the content to make it relevant to each new audience, chances are you're spamming.

Consider for example a notification about an MVP Office Hours conference call, offered free of charge to the community. People share this information with their local user groups, and generally speaking no one complains about this being spam, because the resource is relevant and targeted to users, who are naturally members of user groups.

But is the same notification appropriate for an official group that's created specifically for a feature or different topic of interest, such as the Salesforce1 group or the Communities Implementation group? Now the cross-post is starting to smell like spam, unless additional context can be provided to explain that there will be a dedicated segment to mobile apps or Communities.

3. Your post has no clear relevance to the audience


Take a look at the charter or description of a group or any channel, and assess whether your post has relevance and value to add to that group. Obviously if the value is unclear or loosely associated, your post is probably spam. But I think it is possible to tweak or augment a post with additional information to make it relevant to a new audience.

Let's use Lightning Process Builder as an example in the context of Salesforce. A generic statement that adds unclear value could be, "Process Builder is the future of declarative automation on the Salesforce1 Platform." Posting this as-is to a Sales Effectiveness group is probably a bad idea. But adding additional context could make the post relevant, such as, "Here's an example of a process that intelligently populates the Next Step field with a recommended action based on field values on the opportunity and account."

4. You have no prior relationship with the audience


This one should be a no-brainer. Did you join a group or cross-post to a group just to share a piece of content? Even if you're doing it with the best of intentions, your action could be seen as spam. This is a human consideration, not necessarily a technicality.

Closing thoughts


Use common sense. None of the signs above are hard and fast rules. But instead, think of them as factors that comprise a "contributor score" similar to a Sender Score. Reputations are difficult to build and easy to ruin, so don't lie to yourself about what you're trying to do.

Treat your audience as real people, and imagine you were telling each person individually about whatever content you're about to share. If you think the vast majority of people will be appreciative, go for it. If not, you should probably err on the side of caution.

P.S. At the risk of being seen as promoting religion, I also want to share Matthew 18:15-17. This is 5 sentences well written about conflict resolution that applies to resolving differences of opinion about what is and isn't spam.

Wednesday, December 3, 2014

Where are my Featured Search images in Kokua?

If you're trying out the new Community Designer feature (in beta still, as of Winter '15), you may run into a bit of trouble getting the images to appear correctly for Featured Search on Kokua's homepage. At a high level, there are the three key requirements to getting an images to appear on the homepage, explained in more detail below.

  • Name the image as DataCategoryUniqueName-s.jpg
  • Upload the image as an asset using Site.com Studio
  • Enter a value using merge fields into the Category Image URL: {!Global.PathPrefix}/{!DataCategory.Name}.jpg

Note: The ".jpg" extension is not required, but it must match what you entered for the Category Image URL.

Name the image


To figure out what to name an image for a data category, you need to know the data category's Category Unique Name is. To figure this out, first go to Setup > Customize > Data Categories > Data Category Setup. Next, click the Actions button next to an existing data category, then click Edit Category. Now the Category Unique Name field and value will be exposed.


For the Featured Search box on the homepage, you need to specify 's' (stands for "square") for the <size> portion of the filename. Here are some examples.

Examples of image filenames for Featured Search
Data Category Unique NameImage TypeImage Filename
Technology_EnablementJPEGTechnology_Enablement-s.jpg
Customer_EngagementJPEGCustomer_Engagement-s.jpg
StrategyPNGStrategy.png

Note: The Winter '15 documentation for Featured Search says that you should use the convention <datacategoryname>-<size>.<filetype>. However, a more accurate convention is <datacategoryuniquename>-<size>.<filetype>.

Upload the image


This part is relatively simple. All you need to do is open Site.com Studio for the community's site, and then upload the image as an asset.

  1. Go to Setup > Customize > Communities > All Communities
  2. Click Community Designer next to your community
  3. Click the top header's picklist next the the word "Communities", and click Go to Site.com Studio
  4. In the left-hand navigation tree, click Assets under All Site Content
  5. Click the Import... button, and upload your image


Note: If you upload a .zip file where the images are stored in folders, you will need to tweak your Category Image URL in the last step.

Enter a value for Category Image URL


Finally, while you're in Site.com Studio, you need to edit the main page and enter a value for the Category Image URL property in Featured Search.
  1. On the Overview tab, click Site Pages under All Site Content
  2. Double-click main under Site Map to open the page
  3. In the Views section, double-click Kokua Home to edit the view
  4. Under Page Structure, click Featured Data Categories
  5. In the Property Editor in the right sidebar, enter this exact value for Category Image URL: {!Global.PathPrefix}/{!DataCategory.Name}.jpg


Note: In the previous step if you uploaded a .zip file where the images are stored in folders, you need to include the folder names in the Category Image URL value, such as: {!Global.PathPrefix}/folder/subfolder/{!DataCategory.Name}.jpg

Friday, November 21, 2014

Login with Facebook for a community with Visualforce

Adding an auth provider (e.g., Login with Facebook) to a Salesforce Communities instance is pretty easy.


The Login with ... button is pretty magical: It knows what community you're logging into, and it knows what URL you're trying to access upon authentication. Based on that information when you click the button, you're taken to the correct authentication URL based on the Auth Provider configuration in Salesforce.

But... for orgs that have customized their login pages with Visualforce, how do you add this button? Luckily, adding the same magical button to a custom Visualforce login page doesn't require you to manually reconstruct the OAuth authentication endpoint. Instead, you can just use the AuthConfiguration.getAuthProviderSsoUrl() method.

Simply put, you need just three things:
  • Your community's base URL
  • The relative path after the base URL to which the user should be taken upon successful authentication. This is also known as the startUrl.
  • The URL Suffix (a.k.a. DeveloperName) of your auth provider (e.g., Facebook) as configured in Salesforce

Once you have this information, all you need to do is create an action in your Apex controller that returns a PageReference object, constructed from the URL returned by AuthConfgiuration.getAuthProviderSsoUrl().


This same approach can be applied to other auth providers as well, such as Twitter or Google.

AuthConfiguration.getAuthProviderSsoUrl(String, String, String) explained

Curious about AuthConfiguration.getAuthProviderSsoUrl(String, String, String)? Here are some notes about the parameters that may not be apparent the first time you read the documentation.

String cUrl


You'll want this to match exactly what you see when you're looking at your community's Administration Settings. Don't add any extra trailing slashes!


String startUrl


This should be the URL relative to the value you put for cUrl, including the leading forward-slash ('/'). For example, if you want to land the user at the Home tab, startUrl should be set to "/home/home.jsp" (again, note the inclusion of the leading forward-slash).

Think about it this way: If you concatenate cUrl and startUrl, exactly as written, you should end up with a valid URL to the desired page or resource within your community.

String developerName


This is the DeveloperName field from the AuthProvider object. Or, you can find the value by looking at the URL Suffix field on the Auth Provider detail page.


You can find this value dynamically by querying the AuthProvider object.

Monday, September 22, 2014

Your request cannot be processed at this time. The site administrator has been alerted.

In setting up and testing self-registration for a new community built on Salesforce Communities, you may encounter this confounding error: "Your request cannot be processed at this time. The site administrator has been alerted."

"Alerted" in the above statement refers to an email alert that went out to the site administrator. But who is the "site administrator"? You can find the email address used for this notification by locating the Site Guest User for your community's Force.com site.
  1. Open Setup > Manage Communities
  2. Click Force.com for the community in question
  3. Click Edit
  4. Change Site Contact to the user who should receive notifications when errors arise with self-registration. Make sure the user's email address is valid.


For sandboxes, make sure your Access to Send Email is set to "All email", under Setup > Email Administration > Deliverability. (Thanks Lynnet!)


Below are a few common reasons why you may be encountering the problem:
  • The community is not published. In case you're working with a community that is offline or in Preview status, you need to publish the community before self-registration will work.
  • The Account Owner does not have a User Role assigned. If you're creating a new Account record on the fly, especially in B2C situations, you need to make sure you assign a default account owner that also has a User Role value. Any role will do, and you can use either a workflow rule or Apex to perform the assignment.
  • The site guest user does not have Create and Read permissions on the Account and Contact objects. Edit Public Access Settings for the community's Force.com site to grant these permissions, along with field permissions for any fields that are included on the self-registration form. Note that by default the site's profile will not have these permissions.
  • Self-registration is not enabled for the community. Go to Manage Communities, click Edit and make sure the Login settings show that self-registration is enabled.

For more details on setting up a community for self-registration, please refer to the Getting Started with Communities guide.

Thursday, March 13, 2014

Allowed User License Changes: Upgrades, Downgrades, Switches?

An infrequent but significant question that companies ask about Salesforce user licenses is: Can I switch from this license to that license? At the time of Winter '14, I could not find an official matrix of allowed user license changes. However, the question lingers, and I balked at the thought of manually trying to change user licenses to see what happens every time I needed an answer.

Using what I hope is a valid approach, I've compiled a matrix of allowed changes, using what licenses existed in my Winter '14 test org. I'm sharing the high-level summary of my approach in case anyone case to reproduce the same results.
  1. Create test profiles for every user license
  2. Run an Apex test to compile the results of every possible change among profiles
Below are the user licenses that were analyzed and included in these results:
  • Chatter External
  • Chatter Free
  • Chatter Only
  • Content Only
  • Customer Community
  • Customer Community Login
  • Customer Portal Manager Custom
  • Customer Portal Manager Standard
  • Force.com - One App
  • Gold Partner
  • High Volume Customer Portal
  • Knowledge Only
  • Partner Community
  • Partner Community Login
  • Salesforce
  • Salesforce Platform
  • Siteforce Only
  • Work.com Only
My wish is that anyone asking the same question can now refer back to this matrix for a quick answer. All feedback on the accuracy of the results will be greatly appreciated.

Monday, February 10, 2014

Recommended Usernames for Salesforce Communities

With the shift from Portals to Communities, salesforce.com delivered an attractive package of changes and improvements for a critical feature. However, one subtle change in Communities produced significant implications for Portals-to-Communities migrations and new Communities implementations: the username namespace.

What do you do with usernames that were once acceptable but can no longer be used? And how do you prevent future collisions with other companies and their communities, so that we all play nicely as multi-tenants in the Salesforce world?

In short, there are a few options you can adopt, depending on your use case and appetite for supporting customizations:
  • The domain-qualified username; or
  • The community-qualified username; or
  • A (domain-community-qualified) hybrid username using both of the above schemes, and probably the best option of the three

All naming conventions are described below, and in all options the optimal implementation requires that you create a custom login page.

Background


Every username has an interesting property: The username must be unique within a given namespace or context. For example, you and I can both use the username "superuser", if you register "superuser" with Twitter and I register "superuser" with Instagram. In this case, Twitter and Instagram represent two unconnected namespaces. But as soon as you try to register the same username with Instagram, you'll get an error telling you that the username is already taken (by me).

Salesforce used to have separate namespaces for every single portal. This means that I could log into my company's org as martyc@slalom.com and also log into a partner portal as martyc@slalom.com, even though the usernames were identical. The reason is that in the Portals age, Salesforce considered my company's org and the partner portal as distinct and separate where usernames were concerned.

But with Salesforce Communities, usernames are all of a sudden pooled together into redesigned namespaces. Partner Community usernames now exist in a namespace that is shared among all internal organizations and partner communities, even including salesforce.com's own Partner Portal. On the other side, the namespace for Customer Community usernames is unique for each org, but the namespace includes Partner Community and internal usernames within the same org.

Companies that want to create a consistent customer or partner experience should choose a naming convention that minimizes the likelihood of username collisions.

Edit: Customer Community usernames share a namespace with other Partner Community and internal usernames within an org, but not with other orgs. The post originally stated that Customer Community usernames were pooled together with Partner Community usernames and internal usernames across all orgs. Props to Andy Ognenoff for noting this inaccuracy!

Domain-Qualified Usernames


The domain-qualfiied username is a naming convention where a community user's username also contains that user's email domain. For example, John Smith is a Salesforce user at Acme Corporation, which has a partnership with the Zenith Group. Knowing that John's regular username is jsmith@acme.com (also his email), Zenith's admin sets John's partner community username to be jsmith.acme.com@zenith.com.

Effectively, the domain-qualified username contains the following elements, which can be joined and transformed as you wish. The example above shows a period between the partner's prefix and domain, with the parent company's domain coming last.
  • Customer/partner email prefix (e.g., jsmith)
  • Customer/partner email domain (e.g., acme.com)
  • Parent company's domain (e.g., zenith.com)

For best results, you should implement a custom login page that accepts the user's email as the username, transforming that email to the community username behind the scenes.



Sample Community Login URL What the User Enters Username Stored in Salesforce Sample Email
https://zenith.force.com/partner/login jsmith@acme.com jsmith.acme.com@zenith.com jsmith@acme.com
https://zenith.force.com/partner/login martyc@slalom.com martyc.slalom.com@zenith.com martyc@slalom.com

Community-Qualified Usernames


The community-qualified username is a naming convention where a community user's username contains an additional "subdomain" after the '@' symbol. For consistency and easy decision-making, you can adopt a community's URL path as the subdomain. For example, Jane Doe is a customer of two divisions within Gamma Corporation, and Jane is also a customer of the Delta Group. Jane logs in as "jdoe" to all three communities, even though Jane's true usernames for the three communities are:

  • jdoe@products.gamma.com
  • jdoe@services.gamma.com
  • jdoe@my.delta.com.

As you can see, the usernames only differ in what comes after the '@' symbol. In this case, they key components in the username are:

  • Unique prefix (e.g., jdoe), self-selected by the user or auto-assigned by the parent company
  • Unique community subdomain (e.g., services.gamma.com), which includes the parent company's primary domain

Again, for best results, you should implement a custom login page. This time the custom page should accept the unique prefix (that comes before the '@' symbol) as the username, and then add on the community subdomain behind the scenes.



Sample Community Login URL What the User Enters Username Stored in Salesforce Sample Email
https://gamma.force.com/products/login jdoe jdoe@products.gamma.com jane.doe@gmail.com
https://gamma.force.com/services/login jdoe jdoe@services.gamma.com jane.doe@gmail.com
https://delta.force.com/my/login jdoe jdoe@my.zenith.com jane.doe@gmail.com

Hybrid Usernames


The (domain-community-qualified) hybrid username is a naming convention that combines the elements of both the domain-qualified username and the community-qualified username. As a result, the hybrid username can provide the following benefits:

  • Intuitive username for the customer or partner. Customers and partners can log in using their emails.
  • Minimized risk of duplicate usernames, across all Salesforce orgs and communities

Inside an org, every community username contains:
* Customer/partner email prefix (e.g., jsmith)
* Customer/partner email domain (e.g., acme.com)
* Unique community subdomain (e.g., services.gamma.com), which includes the parent company's primary domain

Due to the complexity of the stored username, you must implement a custom login page to succeed with this option. The login page should accept the user's email as the username, again transforming that email to the community username behind the scenes.



Sample Community Login URL What the User Enters Username Stored in Salesforce Sample Email
https://zenith.force.com/partner/login jsmith@acme.com jsmith.acme.com@partner.zenith.com jsmith@acme.com
https://zenith.force.com/customer/login martyc@slalom.com martyc.slalom.com@customer.zenith.com martyc@slalom.com
https://gamma.force.com/products/login jane.doe@gmail.com jane.doe.gmail.com@products.gamma.com jane.doe@gmail.com

Other schemes?


If you have other user naming conventions or username schemes for Salesforce Communities, please share them in the comments below!

Monday, September 9, 2013

Adding a Live Agent Chat Side Tab to All Pages in a Community

Chatter Communities gives administrators and web developers a method to implement more advanced customization of the UI, without resorting to fully custom pages or sites through Force.com Sites or Site.com. The means to achieve this customization is through an HTML header or footer, uploaded as a Document in Salesforce. The ability to customize the entire site with HTML gives web developers an easy way to add a Web 2.0 feature to an entire community: live chat side tab via Live Agent.


Similar to the Contact Us side tab shown on salesforce.com (screenshot above), the intent behind the live chat side tab is to enable the following functionality, no matter where a user is in a community:

  • Chat with a customer service agent live, if one available
  • If an agent is unavailable, quickly open a page to log a new case

The steps to achieving this are actually surprisingly simple, and can be tested through a brief tutorial with a new Developer Edition org. The high-level steps are:
  1. Enable Live Agent
  2. Create a Live Agent Deployment, copying the HTML code and pasting it into the community's custom HTML footer
  3. In the HTML footer, add a div with an inline style attribute to become the side tab
  4. Create a Live Agent Chat Button, copying the HTML code and pasting it into the side tab div
  5. Configure a new community to use the custom HTML footer, after uploading it

Monday, September 2, 2013

Custom CSS for Chatter Communities

Chatter Communities allows an organization using Salesforce to quickly deploy a functional, branded portal experience for partners and customers. Communities conveniently allows for a custom HTML header and footer to be added to a community, but it appears that in the Summer '13 release of Salesforce there is no support for using merge fields or to easily pull in custom CSS styles into a community. If you're used to using the URLFOR() function with the apex:stylesheet element in Visualforce, you may feel like something's missing.

Without too much hacking, there are two HTML5-compliant ways to approach this problem in Summer '13:

<style scoped>...</style>

This approach is simple, and any styles defined should be applied to the div id="contentWrapper" element into which the community's HTML header and footer are inserted. The parent div pretty much includes all of the visual content on the page, which makes this approach fairly comprehensive in the scope of its effects.

JavaScript script to insert link elements

Typically in Visualforce, styles are applied through dynamic links to CSS stylesheets stored as static resources. However, to build that dynamic URL in static HTML requires manual construction based on knowledge of Salesforce's URL conventions.

A relative URL to a CSS stylesheet stored within a .zip file loaded as a static resource has the following components:
  • CommunityName: The keyword appended after ServerName, if applicable. This may be blank for a particular community.
  • ResourceNumber: A unique number assigned to a static resource by Salesforce
  • ResourceName: The name (case-sensitive) of the static resource
  • InsidePath: The path inside the .zip file to the CSS stylesheet
The full URL is then constructed by concatenating the following: '/' + CommunityName + '/resource/' + ResourceNumber + '/' + ResourceName + '/' + InsidePath

A few sample URL's are shown below:
  • /cirruscommunity/resource/1378136101000/CirrusStaticResource/styles/layout.css
  • /slalomcommunity/resource/1379138201002/SlalomStaticResource/css/common.css
ResourceNumber can be ascertained by opening the static resource and looking for the string of numbers in the "View file" link's URL. Right-clicking the "View file" link and copying the link address should easily grab the ResourceNumber for you.

Lastly, the following JavaScript script can be edited to add all of the stylesheets you want to the community.

<script type="text/javascript">
  function appendLinkToHead(path) {
    var link = document.createElement("link");
    link.setAttribute("rel", "stylesheet");
    link.setAttribute("type", "text/css");
    link.setAttribute("href", path);
   
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
  } // function appendCommunityLink(String)

  var communityName = "community";
  var resourceNo = "1378136101000";
  var resourceName = "CommunityResource";
 
  var resourcePath = "/" + communityName + "/resource/"
      + resourceNo + "/" + resourceName + "/";
 
  var stylesheets = [
      "library/css/brand.css",
      "library/css/layout.css",
      "library/css/reset.css"];

  for (var i = 0; i < stylesheets.length; i++)
    appendLinkToHead(resourcePath + stylesheets[i]);
</script>