Beacon for iOS
For issues or questions, contact Help Scout support at help@helpscout.com.
Requirements
Please view the requirements for the iOS SDK here on Github.
Supported versions
We make every effort to ensure the Beacon SDK is compatible with the latest, non-beta iOS platform, Swift and Objective-C. If you find a compatibility problem, please contact Help Scout support at help@helpscout.com
View the currently supported versions on the GitHub repository
Useful links
- API reference - Jazzy generated docs for all public classes/methods
- Changelog – get a list of recent changes to the Beacon SDK
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
Swift Package Manager
Beacon is available through Swift Package Manager. To install it, simply follow Apple’s guidance for adding the Beacon-iOS package dependency in Xcode.
CocoaPods
Beacon is available through CocoaPods. To install it, simply add the following line to your Podfile
:
pod 'Beacon'
Beacon is currently distributed as a dynamic framework so the use_frameworks!
flag will also need to be present in your Podfile.
Manually
Beacon can be installed manually by linking the Beacon.xcframework
. To do so, download the Beacon.xcframework.zip
from here and add Beacon.xcframework to your Xcode project.
Additional setup
Photos
The attachments menu for sending a message has code to allow users to take a photo or select one 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
, NSCameraUsageDescription
, NSMicrophoneUsageDescription
and NSPhotoLibraryAddUsageDescription
:
Documents
To access the documents picker in the attachment menu you must create an iCloud container that matches your app’s bundle ID.
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";
user.company = @"Test Company";
user.jobTitle = @"iOS Developer";
user.avatar = @"https://example.com/avatar";
[HSBeacon identify:user];
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings];
Swift
let user = HSBeaconUser()
user.email = "test@example.com"
user.name = "Test User"
user.company = "Test Company"
user.jobTitle = "iOS Developer"
user.avatar = "https://example.com/avatar"
HSBeacon.identify(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 identify:user];
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings signature:@"8235545a15c6f41b64e3c47e5c94d3..."];
Swift
let user = HSBeaconUser()
user.email = "test@example.com"
HSBeacon.identify(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
Objective-C
[HSBeacon logout];
Swift
HSBeacon.logout()
User attributes
For Help Scout plans with access to Customer Properties, you can pass custom attributes that will be synced to the customer’s record and visible in the Customer Properties sidebar app.
Attribute keys should exactly match Customer Property IDs, which are case-sensitive and can include letters, numbers, hyphens, and underscores, but no other special characters. name
and email
are reserved attribute keys. Attribute values should be of type String.
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
Session attributes
This method allows you to add session-specific information to a new message or chat. By implementing the sessionAttributes
method on the HSBeaconDelegate
protocol, you can pass data into the Beacon visitor activity note that’s only relevant to a specific conversation or chat. We do not sync this data to either the customer profile or the Customer Properties app.
You can add up to 20 attribute-value pairs. Each attribute label can contain up to 100 characters, and each value can contain up to 10,000 characters.
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)
}
}
SwiftUI
import Beacon
import Foundation
class BeaconDelegate: NSObject, HSBeaconDelegate {
static let shared = BeaconDelegate()
var prefill: ((HSBeaconContactForm) -> Void)?
var email: String?
var name: String?
var subject: String?
var text: String?
func prefill(_ form: HSBeaconContactForm) {
if let prefill = prefill {
prefill(form)
} else {
if let email = email {
form.email = email
}
if let name = name {
form.name = name
}
if let subject = subject {
form.subject = subject
}
if let text = text {
form.text = text
}
}
}
}
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 identified using the identify
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()
Navigate to a specific screen
The HSBeacon navigate
method opens the Beacon and shows a specific screen. Swift apps have the option to take advantage of the BeaconRoute
enum when calling this method. Available routes are:
Objective-C
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon navigate:@"/" beaconSettings: settings]; // welcome screen
[HSBeacon navigate:@"/ask/" beaconSettings: settings]; // ask screen
[HSBeacon navigate:@"/ask/message/" beaconSettings: settings]; // message screen
[HSBeacon navigate:@"/ask/chat/" beaconSettings: settings]; // chat screen
[HSBeacon navigate:@"/answers/" beaconSettings: settings]; // answers screen
[HSBeacon navigate:@"/previous-messages/" beaconSettings: settings]; // previous conversations screen
[HSBeacon navigate:@"/docs/search?query=help" beaconSettings: settings]; // equivalent to HSBeacon search
[HSBeacon navigate:@"/docs/article?query=articleId" beaconSettings: settings]; // equivalent to HSBeacon openArticle
Swift
let settings = HSBeaconSettings(beaconId: "beacon-id")
HSBeacon.navigate(BeaconRoute.home, settings: settings) // welcome screen
HSBeacon.navigate(BeaconRoute.ask, settings: settings) // ask screen
HSBeacon.navigate(BeaconRoute.askMessage, settings: settings) // message screen
HSBeacon.navigate(BeaconRoute.askChat, settings: settings) // chat search
HSBeacon.navigate(BeaconRoute.answers, settings: settings) // answers screen
HSBeacon.navigate(BeaconRoute.previousMessages, settings: settings) // previous conversations screen
HSBeacon.navigate(BeaconRoute.search("help"), settings: settings) // equivalent to HSBeacon search
HSBeacon.navigate(BeaconRoute.article("articleId"), settings: settings) // equivalent to HSBeacon openArticle
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 |
focusModeOverride |
HSBeaconFocusMode | If your Beacon has Docs and Messaging (email or chat) enabled, the mode controls the user experience of the Beacon. Learn more |
enablePreviousMessages |
Bool | Enable or disable previous messages (only if messaging is enabled); the default is enabled. |
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 |
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, you can define a string resource with the same key, and we’ll use that in preference over the Beacon Builder string value. You will also need to include the useLocalTranslationOverrides
bool set to true
in your Beacon’s General Options object for these changes to take effect.
You can find a list of available strings in the Beacon Example app.
Mobile Specific Strings
Note some strings are iOS/Mobile specific and there isn’t a Beacon Builder equivalent but these can also be overridden in the same way.
Misc
String Key | Default Value |
---|---|
Support |
Support |
Attachments |
Attachments |
dropdownPickerClear |
Clear |
dropdownPickerDone |
Done |
Discard |
Discard |
Cancel |
Cancel |
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 |
OK |
OK |
Attachment Picker Errors
String Key | Default Value |
---|---|
This application is not entitled to access iCloud |
This application is not entitled to access iCloud |
There doesn't seem to be a photo taken yet. |
There doesn't seem to be a photo taken yet |
To give permissions tap on 'Change Settings' button |
To give permissions tap on 'Change Settings' button |
Unable to save video: %@ |
Unable to save video: %@ |
Unable to save photo: %@ |
Unable to save photo: %@ |
Selected media type is unsupported |
Selected media type is unsupported |
retry |
Retry |
Chat
String Key | Default Value |
---|---|
genericEmailAddress |
email@address.com |
chatMessageSendingFailed |
Message failed to send. Tap to try again. |
chatAttachmentSendingFailed |
Attachment failed to send. Tap to try again. |
chatAttachmentUnsupportedFile |
Unsupported file. Message not sent. |
chatAttachmentSending |
Sending... |
chatAttachmentDownloading |
Downloading |
chatAttachmentDownloadFailed |
Download failed |
chatAttachmentTryAgain |
Tap to try again |
chatMaxAttachmentsReached |
Sorry, you can’t send more than %@ attachments. |
chatMinimizeOrEndSessionMessage |
Minimize or end your chat session |
backToHome |
Back to Home |
viewConversation |
View Conversation |
chatbotAgentDefaultAgent |
an agent |
warningDiscardRating |
Are you sure you want to exit and discard your rating? |
chatRatingGood |
Good (Voice over only) |
chatRatingNeutral |
Neutral (Voice over only) |
chatRatingBad |
Bad (Voice over only) |
chatEndedTitle |
Chat Ended |
closeAfterRating |
Leave Chat |
declineChatRating |
No Thanks |
Previous Messages
String Key | Default Value |
---|---|
previousMessagesEmptyText |
No messages found |
previousMessagesConfirmEmailToViewConversations |
Please confirm your email address to see previous conversations |
Custom fields validation
String Key | Default Value |
---|---|
customFieldsValidationLabel |
Please complete all fields |
customFieldsMaximumLengthValidationLabel |
You have typed more characters than allowed |
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 or chats 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.
NOTE: Automatic handling does not work in secure mode. If you are using secure mode please follow the steps for Manual setup.
Objective-C
[HSBeacon initializeAutomaticPushNotificationHandlingWithMethodSwizzling:BOOL overrideUserNotificationCenterDelegate:BOOL];
Swift
HSBeacon.initializeAutomaticPushNotificationHandling(withMethodSwizzling: Bool, overrideUserNotificationCenterDelegate: Bool)
Manual setup
When the app starts up, initialize the notification system for Beacon by calling initializeBeaconPushNotificationSupport
Objective-C
[HSBeacon initializeBeaconPushNotificationSupport];
Swift
HSBeacon.initializeBeaconPushNotificationSupport()
Then you need to register the token by calling setDeviceToken
from your Application didRegisterForRemoteNotificationsWithDeviceToken
method.
Objective-C
[HSBeacon setDeviceToken:token];
Swift
HSBeacon.setDeviceToken(token)
Let Beacon know if registering for a token failed by calling failedToRegisterForRemoteNotificationsWithError
from your application didFailToRegisterForRemoteNotificationsWithError
method.
Objective-C
[HSBeacon failedToRegisterForRemoteNotificationsWithError:error];
Swift
HSBeacon.failedToRegisterForRemoteNotificationsWithError(error)
For any of the delegate methods that handle push notifications (application:didReceiveRemoteNotification:
or userNotificationCenter:didReceiveNotificationResponse
), check for a Beacon notification using:isBeaconPushNotification
method then invoke handlePushNotification
if it matches.
Objective-C
if ([HSBeacon isBeaconPushNotification:userInfo]) {
[HSBeacon handlePushNotification:userInfo beaconSettings:beaconSettings];
}
Swift
if HSBeacon.isBeaconPushNotification(userInfo) {
HSBeacon.handlePushNotification(userInfo, beaconSettings: settings)
}
Last but not least, to handle whether notifications are displayed to the user you should forward any relevant notifications from your UNUserNotificationCenterDelegate
userNotificationCenter:willPresentNotification:withCompletionHandler:
method to Beacon through the handleWillPresentNotification
method. Beacon will only call the completionHandler
if it is a Beacon notification.