Beacon for iOS

For issues or questions, contact Help Scout support at help@helpscout.com.

Requirements

The Beacon SDK requires iOS 9.0+.

The Beacon SDK 2.0 beta requires iOS 11.0+.

2.0 beta notes

The Beacon SDK 2.0 beta adds support for live chat. The following features are currently unavailable in the beta:

  • Uploading and viewing attachments
  • Push notification support

Known issues

  • The text which appears when connecting to an agent is not customizable
  • The text which appears when connecting to an agent may appear multiple times if the agent drops the session
  • An incorrect status message is displayed when the customer leaves a chat before it was accepted
  • Status messages may appear out of order when the app comes back from the background
  • A chat session crashes when ending on iOS 11
  • Invalid TLDs inside an email address cause the chat session to hit an irrecoverable error
  • Previous chat conversations do not appear in the Previous Conversations screen
  • The option to minimize the chat, rather than end it, is not yet available
  • The customer may not be able to navigate out of the chat menu when sending a message on iOS 11
  • The customer’s email address may not be remembered through multiple chat sessions; forcing you to enter it each time

Sample application

We’ve created an open-source example application that you can reference during your implementation.

To run the example project, clone the Beacon repo and run pod install from the Example directory. Once the installation is complete, open Beacon Example.xcworkspace and run the Beacon Example scheme.

Installation

CocoaPods

Beacon is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Beacon'

To install the Beacon SDK with beta Chat support, use this:

pod 'Beacon', '~> 2.0.beta'

Carthage

You can install Beacon using Carthage by adding the following line to your Cartfile and then following the Carthage installation instructions:

github "helpscout/beacon-ios-sdk"

Manually

Beacon can be installed manually by linking the Beacon framework and bundle. To do so, download the Beacon framework from this GitHub repo and integrate it similar to how Carthage integrates frameworks.

Next, ensure your project is linking against the following system frameworks:

  • UIKit
  • Foundation
  • MobileCoreServices
  • Photos
  • QuickLook
  • SafariServices
  • UserNotifications
  • WebKit

Finally, ensure your project includes -all_load in its OTHER_LINKER_FLAGS build setting.

Additional setup

Photos

The attachments menu for sending a message has code to allow users to take a photo or select a photo from their photo library. Even if you have attachments disabled, Apple flags usage of these APIs; so, it requires a description string in the app’s Info.plist file.

The required settings are NSPhotoLibraryUsageDescription and NSCameraUsageDescription:

Documents

To access the documents picker in the attachment menu, you’ll need the entitlements for iCloud and iCloud Containers. The ‘Import file from’ menu option throws an error message without these entitlements.

Push notifications

If you do not already have push notifications active in your application, you may receive a warning when uploading to App Store Connect. Similar to Photos, App Store Connect flags usage of these APIs in code independent of whether you invoke them or not.

Usage

You can find setup code and your Beacon ID in the web Beacon builder by clicking “Installation” on the left sidebar, then navigating to “iOS” in the options displayed at the top.

Usage of the Beacon SDK requires an HSBeaconSettings object, which you initialize using your Beacon ID. After you have created a settings object, you can display the Beacon modal view controller via HSBeacon:

Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings];
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.open(settings)

If you need more control over the presentation, then you can open Beacon with a presentingViewController. You might do this if you’re trying to open Beacon from a view controller that is itself presented modally.

Objective-C
UIViewController *viewController = [[UIViewController alloc] init];
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings fromViewController:viewController];
Swift
let viewController = UIViewController()
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.open(settings, from: viewController)

Authenticating users

You can provide the name and email address to pre-populate and hide the fields on the ‘Create a message’ screen.

Normal mode

Normal mode authentication requires a user’s email address as the user identifier.

Objective-C
HSBeaconUser *user = [[HSBeaconUser alloc] init];
user.email = "test@example.com"
user.name = "Test User";

[HSBeacon login:user];

HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings];
Swift
let user = HSBeaconUser()
user.email = "test@example.com"
user.name = "Test User";

HSBeacon.login(user)

let settings = HSBeaconSettings(beaconId: "123")
HSBeacon.open(settings)

Secure mode

If you provide a valid signature, you can use it to authenticate a user in Secure Mode and retrieve their previous conversations.

Note: you should not store the secret key in the app; instead, your server should provide the computed signature value.

Objective-C
HSBeaconUser *user = [[HSBeaconUser alloc] init];
user.email = @"test@example.com";
[HSBeacon login:user];

HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings signature:@"8235545a15c6f41b64e3c47e5c94d3..."];
Swift
let user = HSBeaconUser()
user.email = "test@example.com"
HSBeacon.login(user)

let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.open(settings, signature: "8235545a15c6f41b64e3c47e5c94d3...")

Logout

Calling this method resets the current Beacon state, and clears the following data stored in the app-specific Keychain:

  • Device ID (UUID generated specifically for Beacon to allow access to Previous Messages from this device only)
  • Name
  • Email
Objective-C
[HSBeacon logout];
Swift
HSBeacon.logout()

User attributes

HSBeaconUser supports the addition of up to 30 attributes. These are arbitrary key-value pairs used to track custom data attributes that are then synced with the customer’s Help Scout profile and displayed in the Beacon sidebar app. You can add any attribute names except for “name” and “email.” The attributes can only take values of type String (E.g: phone: “1-999-999-9999”” or “Subscription”: “Free Plan”). Here’s some example code:

Objective-C
HSBeaconUser *user = [[HSBeaconUser alloc] init];
[user addAttributeWithKey:@"key" value:@"attribute value"];
Swift
let user = HSBeaconUser()
user.addAttribute(withKey: "key", value: "attribute value")

You may also remove specific attributes, or clear the entire set:

Objective-C
HSBeaconUser *user = [[HSBeaconUser alloc] init];
[user removeAttributeWithKey:@"key"]; // Remove one attribute
[user clearAttributes]; // Clear all attributes
Swift
let user = HSBeaconUser()
user.removeAttribute(withKey: "key") // Remove one attribute
user.clearAttributes() // Clear all attributes

Prefilling the contact form

By implementing the prefill method on the HSBeaconDelegate protocol, you can pre-populate the contact form data. You can fill any of the fields: name, email, subject, the body of the message (text), custom fields, and attachments. Note a maximum of three attachments is permitted. Unlike when using Secure Mode, the name and email fields remain visible and editable.

For how to determine the ids for custom field population, see this documentation for the Beacon web component.

The delegate attribute of the settings object needs to be set to the instance implementing the HSBeaconDelegate protocol.

Objective-C
- (void)prefill:(HSBeaconContactForm *)form {
    form.name = @"Steve Aoki";
    form.email = @"steve@aoki.com";
    form.subject = @"Need help with invoice";
    form.text = @"Hello, I need some help with my invoice. See attached PDF...";
    [form addCustomFieldValue: @"Question" forId: 5678];
    NSData *invoiceData = [NSData dataWithContentsOfFile:@"/path/to/invoice.pdf"];
    [form addAttachment: @"invoice.pdf" data:invoiceData];
}
Swift
extension ViewController: HSBeaconDelegate {
    func prefill(_ form: HSBeaconContactForm) {
        form.name = "Steve Aoki"
        form.email = "steve@aoki.com"
        form.subject = "Need help with invoice"
        form.text = "Hello, I need some help with my invoice. See attached PDF..."
        form.addCustomFieldValue("Question", forId: 5678)
        let invoiceData = try! Data(contentsOf: URL(fileURLWithPath: "/path/to/invoice.pdf"))
        form.addAttachment("invoice.pdf", data: invoiceData)
    }
}

Resetting the contact form

Reset the contact form by clearing all of its fields, custom fields and attachments.

If your Beacon is in Normal Mode, calling reset clears all contact form fields, including name and email address.

If your Beacon is in Secure Mode, calling reset does not clear the customer’s name or email address, those inputs remain hidden.

Please note that if a customer is logged-in using the login method, then their name and email address won’t be cleared with this method, you’ll have to call logout to clear these fields.

Objective-C
[HSBeacon reset];
Swift
HSBeacon.reset()

The HSBeacon navigate method opens the Beacon and shows a specific screen. Available routes are:

Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon navigate:@"/" beaconSettings: settings]; // welcome screen
[HSBeacon navigate:@"/ask/message/" beaconSettings: settings]; // message screen
[HSBeacon navigate:@"/docs/search?query=help" beaconSettings: settings]; // equivalent to HSBeacon search
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.navigate("/", beaconSettings: settings) // welcome screen
HSBeacon.navigate("/ask/message/", beaconSettings: settings) // message screen
HSBeacon.navigate("/docs/search?query=help", beaconSettings: settings) // equivalent to HSBeacon search

Opening with search results

The HSBeacon search method searches Docs articles and loads the results screen.

Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon search:@"HIPAA" beaconSettings: settings];
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.search("HIPAA", beaconSettings: settings)

Opening to an article

You can use the HSBeacon openArticle method to open a specific Docs article within Beacon, using the article’s ID.

Article IDs are found in Help Scout by navigating to the article and copying the article ID from the URL. The URL is structured like this: https://secure.helpscout.net/docs/[COLLECTION ID]/article/[ARTICLE ID]/.

Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openArticle:@"DOCS_ARTICLE_ID" beaconSettings: settings];
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.openArticle("DOCS_ARTICLE_ID", beaconSettings: settings)

Opening to the contact form

Open to the contact form screen. Note: requires the Beacon to have messaging enabled.

Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon navigate:@"/ask/message" beaconSettings:settings signature:nil];
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.navigate("/ask/message/", beaconSettings: settings)

Custom suggestions

The suggest method allows you to programmatically change the default list of suggestions setup in the Beacon Builder.

Article IDs are found in Help Scout by navigating to the article and copying the article ID from the URL. The URL is structured like this: https://secure.helpscout.net/docs/[COLLECTION ID]/article/[ARTICLE ID]/.

Custom suggestions only get loaded when displaying the Beacon. If the Beacon is not present, loading the custom suggestion data queues it up for the next Beacon display.

Objective-C
[HSBeacon suggest:@[@"DOCS_ARTICLE_ID_1", @"DOCS_ARTICLE_ID_2"]];
Swift
HSBeacon.suggest(["DOCS_ARTICLE_ID_1", "DOCS_ARTICLE_ID_2"])

You can also suggest URLs that are not Docs articles. This is what the syntax would need to look like for custom links:

id<HSBeaconSuggestionItem> article1 = [[HSBeaconArticleSuggestion alloc] initWithId:@"DOCS_ARTICLE_ID_1"];
id<HSBeaconSuggestionItem> link =  [[HSBeaconLinkSuggestion alloc] initWithUrl:[NSURL URLWithString:@"https://www.helpscout.com"] text:@"Label for the Suggestion"];
id<HSBeaconSuggestionItem> article2 = [[HSBeaconArticleSuggestion alloc] initWithId:@"DOCS_ARTICLE_ID_1"];
[HSBeacon suggestWithItems:@[article1, link, article2]];
Swift
HSBeacon.suggest(with: [
    HSBeaconArticleSuggestion.init(id: "DOCS_ARTICLE_ID_1"),
    HSBeaconLinkSuggestion.init(url: URL.init(string: "https://helpscout.com"), text: "Label for the Suggestion"),
    HSBeaconArticleSuggestion.init(id: "DOCS_ARTICLE_ID_2")
    ])

To expand a little further… Perhaps you’d like to display localized Docs articles based upon a customer’s device language. In the below example, we detect a device language of Spanish 🇪🇸 (“es”), and return Spanish articles:

let language = Locale.current.languageCode
if (language == "es") {
    HSBeacon.suggest(["SPANISH_DOCS_ARTICLE_ID_1",
                      "SPANISH_DOCS_ARTICLE_ID_2",
                      "SPANISH_DOCS_ARTICLE_ID_3"])
}

If you’d like to revert to the default suggestion list from the Beacon Builder, you can call suggest with an empty array.

Open and close events

These methods allow you to hook up to open and close events in the lifecycle of the Beacon to perform custom actions. Example usage:

# pragma mark HSBeaconDelegate
-(void)onBeaconInitialOpen:(HSBeaconSettings *)beaconSettings {
    NSLog(@"First open for Beacon %@", beaconSettings.beaconId);
}

-(void)onBeaconOpen:(HSBeaconSettings *)beaconSettings {
    NSLog(@"Opened Beacon %@", beaconSettings.beaconId);
}

-(void)onBeaconInitialClose:(HSBeaconSettings *)beaconSettings {
    NSLog(@"First close for Beacon %@", beaconSettings.beaconId);
}

-(void)onBeaconClose:(HSBeaconSettings *)beaconSettings {
    NSLog(@"Closed Beacon %@", beaconSettings.beaconId);
}
Swift
extension ViewController: HSBeaconDelegate {
    func onBeaconInitialOpen(_ beaconSettings: HSBeaconSettings) {
        print("First open for Beacon \(beaconSettings.beaconId)")
    }

    func onBeaconOpen(_ beaconSettings: HSBeaconSettings) {
        print("Opened Beacon \(beaconSettings.beaconId)")
    }

    func onBeaconInitialClose(_ beaconSettings: HSBeaconSettings) {
        print("First close for Beacon  \(beaconSettings.beaconId)")
    }

    func onBeaconClose(_ beaconSettings: HSBeaconSettings) {
        print("Closed Beacon \(beaconSettings.beaconId)")
    }
}

Settings customization

You can set various options on the HSBeaconSettings object to override the Beacon Builder configuration.

General options

Name Type Description
messagingEnabled
Bool Enable or disable the contact options
docsEnabled
Bool Enable or disable the Docs integration
chatEnabled
Bool Enable or disable the Chat feature
beaconTitle
String The navigation title shown on the initial Beacon screen (only if Docs are enabled); the default is "Support."
useNavigationBarAppearance
Bool If this is true, then Beacon uses the tint colors defined via UIAppearance, providing they are not nil; otherwise, it uses the Beacon color.
color
UIColor Brand color for your Beacon; the useNavigationBarAppearance option overrides this value.
tintColorOverride
UIColor Replaces the default blue color used for clickable text throughout Beacon
useLocalTranslationOverrides
Bool You may customize the user-facing strings in Beacon locally using HSBeaconSettings, telling Beacon to look for a BeaconLocalizable.strings file. You can find an example of this in the Beacon Example app. If you do not set this flag, we use the translations provided in Beacon Builder. We also have French translations thanks to Github user @amolieres
messagingSettings
HSBeaconMessagingSettings This object holds several messaging specific overrides you can set client-side; see below for a list of values

Contact form options

These are set on the messagingSettings settings object on HSBeaconSettings.

Name Type Description
contactFormCustomFieldsEnabled
Bool Enable or disable Custom Fields
contactFormShowNameField
Bool Display an editable Name field
contactFormShowSubjectField
Bool Display an editable Subject field
contactFormAllowAttachments
Bool Enable or disable file attachments
showGetInTouch
Bool Show a contact link on the Beacon home screen
showPrefilledCustomFields
Bool Display pre-filled Custom Fields

Translation strings

Beacon SDK can use a custom localizable strings file in order to override the strings displayed to the customer. By providing a BeaconLocalizable.strings file, Beacon will look for the matching keys and use the values found in that strings file instead.

You can find a list of available strings in the Beacon Example app.

Mobile Specific Strings

String Key Default Value
Support
Support
Attachments
Attachments
dropdownPickerClear
Clear
dropdownPickerDone
Done
customFieldsMaximumLengthValidationLabel
You have typed more characters than allowed
invalidConfig
Choose a Docs Site or Mailbox to see your Beacon in action!

Attachment Picker Strings

String Key Default Value
Take Photo
Take Photo
Use Last Photo
Use Last Photo
Choose from Library
Choose from Library
Import File from
Import File from
Cancel
Cancel
OK
OK

Chat Strings

String Key Default Value
chatbotConfirmationMessage
Thanks! Someone from our team will jump into the chat soon.
chatbotName
Help Bot
chatbotGenericErrorMessage
Something went wrong sending your message, please try again in a few minutes.
chatbotGreet
Hi there! You can begin by asking your question below. Someone will be with you shortly.
chatbotPromptEmail
Got it. Real quick, what's your email address? We’ll use it for any follow-up messages.
chatbotInvalidEmailMessage
Looks like you've entered an invalid email address. Want to try again?
chatbotInactivityPrompt
Since the chat has gone idle, I'll end this chat in a few minutes.
chatbotAgentDisconnectedMessage
%@ has disconnected from the chat. It’s possible they lost their internet connection, so I’m looking for someone else to take over. Sorry for the delay!
chatbotAgentConnectedMessage
Connected with %@
chatbotAgentDefaultAgent
an agent

Push notifications

NOTE: There is no admin UI in Help Scout currently where you can manage your push notification certificates. If you would like to try out this feature, you can email your APNS certificate (as a p12 file with no password) and your bundle ID to help@helpscout.com, and we’ll set it up manually for you.

The push notification support allows your users to receive push notifications when a support agent replies to one of their messages sent from the Beacon SDK. Clicking the notification opens Beacon and takes the user to the conversation.

Automatic handling

Calling the initializeAutomaticPushNotificationHandlingWithMethodSwizzling method automatically adds Push notification support by wrapping your existing push notification methods.

Manual setup