Beacon for iOS

For issues or questions, contact Help Scout support at


The Beacon SDK requires iOS 9.0+.

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.



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

pod 'Beacon'


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

github "helpscout/beacon-ios-sdk"


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


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, usage of these APIs is flagged by Apple and requires a description string in the app’s Info.plist file.

The required settings are NSPhotoLibraryUsageDescription and NSCameraUsageDescription:


To access the documents picker in the attachment menu, you’ll need the entitlements for iCloud and iCloud Containers. Without the entitlements, an error message will be thrown via the delegate on the ‘Import file from’ menu option.

Push Notifications

You may recieve a warning when uploading to App Store connect related to push notifications if they aren’t already active in your application. Similar to Photos, App Store Connect will flag usage of these APIs in code even if they aren’t invoked in the app.


You can find basic 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.

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

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

If you need more control over the presentation then you can open Beacon with a presentingViewController. One rationale for doing this would be if you’re trying to open Beacon from a view controller that is itself presented modally.

UIViewController *viewController = [[UIViewController alloc] init];
HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings fromViewController:viewController];
let viewController = UIViewController()
let settings = HSBeaconSettings(beaconId: "beacon-id"), 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 an user’s email address as the user identifier.

HSBeaconUser *user = [[HSBeaconUser alloc] init]; = "" = "Test User";

[HSBeacon login:user];

HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon openBeacon:settings];
let user = HSBeaconUser() = "" = "Test User";


let settings = HSBeaconSettings(beaconId: "123")

Secure Mode

If a valid signature is provided, it can be used to authenticate a user in Secure Mode and retrieve their previous conversations. Secure Mode ensures that the visitor is who they say they are.

Note: the secret key should not be stored in the app; instead your server should provide the computed signature value.

HSBeaconUser *user = [[HSBeaconUser alloc] init]; = @"";
[HSBeacon login:user];

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

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


If your Beacon is in Normal Mode (you aren’t using Secure Mode), there may be a case for calling this method. The current Beacon state will be reset and the following data stored in the app-specific Keycahin will get cleared:

  • Device ID (UUID generated specifically for Beacon to allow access to Previous Messages from this device only)
  • Name
  • Email
[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”.

Here’s some example code:

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

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

HSBeaconUser *user = [[HSBeaconUser alloc] init];
[user removeAttributeWithKey:@"key"]; // Remove one attribute
[user clearAttributes]; // Clear all attributes
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. Unlike when using secure mode, the name and email fields will 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 will need to be set to the instance implementing the HSBeaconDelegate protocol.

# pragma mark HSBeaconDelegate
-(void)prefill:(HSBeaconContactForm *)form { = @"Steve Aoki"; = @"";
    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];
extension ViewController: HSBeaconDelegate {
    func prefill(_ form: HSBeaconContactForm) { = "Steve Aoki" = ""
        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

Resets the contact form by clearing all of its fields, custom fields and attachments. If your Beacon is in Normal Mode, calling reset will clear all contact form fields, including name and email address.

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

Please note that if a customer has been identified using the login method, then their name and email address won’t be cleared with this method, you’ll have to use logout for this purpose.

[HSBeacon reset];

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

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
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.

HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:@"beacon-id"];
[HSBeacon search:@"hippa" beaconSettings: settings];
let settings = HSBeaconSettings(beaconId: "beacon-id")"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 can be found in Help Scout by navigating to the article and copying the article ID from the URL. The URL is structured like this:[COLLECTION ID]/article/[ARTICLE ID]/.

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

Custom suggestions

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

Article IDs can be found in Help Scout by navigating to the article and copying the article ID from the URL. The URL is structured like this:[COLLECTION ID]/article/[ARTICLE ID]/.

Custom suggestions will only get loaded when the Beacon is shown. If the Beacon is not present, loading the custom suggestion data will get queued up for the next Beacon display.

[HSBeacon suggest:@[@"DOCS_ARTICLE_ID_1", @"DOCS_ARTICLE_ID_2"]];
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:@""] text:@"Label for the Suggestion"];
id<HSBeaconSuggestionItem> article2 = [[HSBeaconArticleSuggestion alloc] initWithId:@"DOCS_ARTICLE_ID_1"];
[HSBeacon suggestWithItems:@[article1, link, article2]];
HSBeacon.suggest(with: [
    HSBeaconArticleSuggestion.init(id: "DOCS_ARTICLE_ID_1"),
    HSBeaconLinkSuggestion.init(url: URL.init(string: ""), text: "Label for the Suggestion"),
    HSBeaconArticleSuggestion.init(id: "DOCS_ARTICLE_ID_2")

To expand a little further… Perhaps you’d like to display localised 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") {

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

Dismissing the Beacon

The HSBeacon dismissBeacon method will remove the Beacon push notifications if the Beacon view controller is present. This is useful for cases such as handling your own push notifications or univeral links.

[HSBeacon dismissBeacon:^{ NSLog(@"All done!"); }];
HSBeacon.dismiss { print("All done!") }

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);
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.

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

Messaging Settings object

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

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 and we’ll set it up manually for you.

The push notification support allows your users to recieve push notifications when a support agent replies to one of their messages sent from the Beacon SDK. Clicking the notification will open Beacon and take the user to the conversation.

Automatic handling

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

Manual setup