The Embrace Developer Hub

Welcome to the Embrace documentation. You'll find comprehensive guides and documentation to help you start working with Embrace as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started

Integration Guide

iOS Get Started Guide

To get started with Embrace for iOS, the basic integration is four simple steps and should take less than 15 minutes. If you are in front of your Mac and ready to code, please use the self-service flow. To ask us questions directly, join the Embrace Slack community.

Once you complete the initial integration steps, you can verify its success by reviewing events as they happen in real-time. Within the Embrace dashboard, while you are still attached to the debugger, go to the Recent Sessions page on the left-hand menu. Select the Debugger tab in the upper menu. Locate and click into your session under Live Sessions. You should see your events.

To fully realize Embrace's value in (i) development and (ii) post app release, a few more features are recommended. This include integrating logs and moments, defining your customer segments and uploading dSYMs. Please see the Recommended Configuration guide below.


Step 1: Install the Embrace SDK

FAQ: Common Questions and Solutions

The Embrace SDK is available through CocoaPods. (If you do not use CocoaPods, please download the SDK following these instructions.)

Add the EmbraceIO pod to your Podfile:

pod 'EmbraceIO'

To continue, run the following command in your terminal after updating your Podfile:

pod install

Step 2: Initialize Embrace

FAQ | API

Add the following two lines to either AppDelegate.swift or AppDelegate.m:

import UIKit
import Embrace // Add import statement

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
      // Add SDK initialization.
      // Replace APP_ID (A 5-character value. For example: "aBc45")      
      
      Embrace.sharedInstance().start(withKey: "APP_ID")
      
      /* Initialize additional crash reporters and 
         any other libraries to track after Embrace, including
         Network Libraries
         3rd party SDKs
      */
      return true
  }
}
#import AppDelegate.h
#import <Embrace/Embrace.h>  // Add import statement

@implementation AppDelegate
- (BOOL)application:(UIApplication *) application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
     	// Add SDK implementation
    	// Replace APP_ID, which is a 5-character value, e.g. "aBc45"

 	   [[Embrace sharedInstance] startWithKey:@"APP_ID"]

      /* Initialize additional crash reporters and 
         any other libraries to track after Embrace, including
         Network Libraries
         3rd party SDKs
      */
  
     return YES;
  }
@end

Step 3: Set Your User Identifiers

FAQ: Identifying Users | API

User lookup is a useful tool to understand and resolve problems quickly. It can help developers and QA teams debug issues during development. You can also utilize user lookup to triage customer complaints post release.

Set the identifiers for your users by adding one or more of the lines below. The best practice is to set the user identifiers early in the startup and whenever a user logs in or registers.

Embrace.sharedInstance().setUserIdentifier("123")
Embrace.sharedInstance().setUsername("abc")
Embrace.sharedInstance().setUserEmail("user@example.com")
[[Embrace sharedInstance] setUserIdentifier:@"123"];
[[Embrace sharedInstance] setUsername:@"abc"];
[[Embrace sharedInstance] setUserEmail:@"user@example.com"];

Step 4: Test the Integration

To verify your integration is working, add an error log to your application:

Embrace.sharedInstance().logMessage(
  "error log with screenshot sent to Embrace (Woo-hoo!)",
  with: .error,
  properties: [:],
  takeScreenshot: true
)
NSString *error = @"error log with screenshot sent to Embrace (Woo-hoo!)";
  [[Embrace sharedInstance] logMessage:error
  withSeverity:EMBSeverityError
  properties:nil
  takeScreenshot: YES];

If you are integrating your app with Embrace for the first time, you will be able to proceed to the next step once a complete session is captured. Complete the session by backgrounding your app and relaunching it. Once you gain access to the rest of the dash and while you are still attached to the debugger, go to the Recent Sessions page on the left-hand menu of the Embrace dashboard. Select Debugger on the upper menu and locate and click into your session under Live Sessions. You should see your events flow in real-time.

In general, data for the entire session is sent to Embrace when the application is sent to the background and reopened.


Recommended Configuration

Crash Reporting

FAQ

Embrace is crash reporter agnostic -- we support both Crashlytics and have our own crash reporting solution (built with KSCrash). If you prefer to use Crashlytics, make sure to initialize Embrace before Fabric so that we can measure your crash rate. You can skip to symbolication.

If you wish to use Embrace's crash solution, here are the steps to capture crashes using our SDK:

  1. Remove all other crash reporters from your application. Using more than one crash reporting solution will lead to crash handler conflicts and dropped crashes.
  2. Create a Embrace-Info.plist file (note the capitalization). Make sure the file is named correctly and included in the app's main bundle. See sample file below.
  3. Create the boolean key CRASH_REPORT_ENABLED in the Embrace-Info.plist file and set the value to YES. Note that if you opened the plist in Source Code mode rather than Property List mode, boolean values are specified as <true/> and <false/> rather than YES and NO.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>API_KEY</key>
    <string>ADD_YOUR_API_KEY_HERE</string>
    <key>CRASH_REPORT_ENABLED</key>
    <true/>
  </dict>
</plist>

If you've completed these steps and do not see a crash in the Embrace dashboard, please verify the following:

  1. The app process is detached from the debugger - otherwise XCode will intercept the crash reports
  2. App was relaunched after crashing - we collect crashes upon next clean app start

If you're still not seeing crashes, please refer to the missing crashes FAQ.


Crash & Log Symbolication

FAQ

By default, a stack trace will only show memory addresses, so it must be symbolicated to display useful information. Symbolication will replace the memory addresses with function names, file paths, and line numbers. To enable symbolication for your builds, you need to upload your dSYM files. The following are instructions to upload your dSYMs with or without enabling Bitcode.

Without Bitcode

After completing each app build, the dSYM files are available on your local machine and ready to be uploaded to Embrace. This process can be automated by adding a build phase to your project which uploads any generated dSYM files after each build.

To configure dSYM uploads for your build process, add a custom Run Script build phase in Xcode.

  1. Navigate to the “Build Phases” tab in your app’s target by selecting "Project Navigator", the project file, and then your target. Select "Build Phases"
  2. Click the + icon in the upper-left and expand new “Run Script” section
  3. Within the Run Script, add the following: EMBRACE_ID=APP_ID EMBRACE_TOKEN=API_TOKEN "${PODS_ROOT}/EmbraceIO/run.sh". Replace APP_ID (5-char string) and API_TOKEN (32-digit hex value) with the values for your application.
  4. Build and run your app

For more information on uploading dSYMs or to debug errors, please refer to the dSYM upload FAQ.

With Bitcode

If you have Bitcode enabled in your project settings, not all the dSYM files available on your Mac will contain the information needed to symbolicate crash reports.The dSYMs needed to fully symbolicate your crashes for release are generated by the App Store (or TestFlight if you use it) when your app is recompiled after upload. These will need to be downloaded using Xcode or iTunes Connect.

You can also upload dSYMs manually on the Settings page in the Embrace dashboard. Upload any and all dSYM files and we will automatically associate them to the correct version and build. Please refer to dSYM uploading for more information.


Startup Performance

FAQ | API

The Embrace SDK automatically records the Startup event once it's initialized. Keep in mind that your Startup can end in multiple locations depending on how the user launched the app (cold start, push notification, deeplink, etc). You'll need to complete the Startup in every view a user can end up in once they launch the app by calling the endAppStartup method. Feel free to add this call as many times as you like.

// Add the following to all view controllers where a Startup can end.

import Embrace

override func viewDidLoad() {
    // ... other code
    Embrace.sharedInstance().endAppStartup()
}
// Add the folliwng to SomeViewController.m

#import <Embrace/Embrace.h>

- (void)viewDidLoad
{
    // ...
    [[Embrace sharedInstance] endAppStartup];
}

To manually disable screenshots for startup, you can set STARTUP_MOMENT_SCREENSHOT_ENABLED to false in the Embrace-Info.plist file. See this section for more details.


Logging

FAQ | API

Log messages are a great tool to gain visibility into a user's session and to debug issues. Add Error, Warning, and Info log messages to provide additional context to your user timelines and to aggregate on counts of expected issues. Embrace does not limit the number of logs and does not require that you turn them off on app release.† Each log message may include a stack trace and screenshot.

// Properties are not required but are shown here as examples.
// A screenshot is captured for Error and Warning logs by default.
// The stack trace is captured for all log types by default.

// Log an error message (takeScreenshot defaults to true)
Embrace.sharedInstance().logMessage("checkout_error", 
    with: .error, 
   properties: [:], //optional
   takeScreenshot: true) //optional

// Log a warning message
Embrace.sharedInstance().logMessage("checkout_retry",
    with: .warning, 
    properties:["foo": "bar"], //optional
    takeScreenshot: false) //optional

// Log an info message (Screenshots cannot be captured for info logs)
Embrace.sharedInstance().logMessage("checkout_success", 
    with: .info, 
    properties:["error": "not_found"]) //optional
// Sample code - note: not all properties are required but are shown here as examples. // Screenshot Default: sent for only Error and Warning log types
// Stacktrace Default: sent for all three log types

// Log an error message (Screenshot default:on)
NSString *error = @"checkout_error";
[[Embrace sharedInstance] logMessage:error 
    withSeverity:EMBSeverityError 
    properties:nil //optional
    takeScreenshot: YES]; //optional

// Log a warning message  (Screenshot default:on)
NSString *warning = @"checkout_retry";
[[Embrace sharedInstance] logMessage:warning 
   withSeverity:EMBSeverityWarning
   properties:@{@"foo": @"bar"} //optional
   takeScreenshot: NO]; //optional

// Log an info message  (Screenshots cannot be captured for info logs)
NSString *info = @"checkout_success";
[[Embrace sharedInstance] logMessage:info 
    withSeverity:EMBSeverityInfo 
    properties:@{@"screen": @"checkout"}]; //optional

Custom properties add even more context around log messages. These are simple key-value attribute pairs that are sent with the log message to provide additional visibility. Both property keys and values function as filters on the App Performance and Logging pages, and are displayed in session timelines. You are limited to 10 properties for any given log message.

For example, if your app has an add-to-cart error message, you can set properties:["item": "widget"] to understand what item may be causing the error. Info logs can have properties:["share": "instagram"] to track which media platform a user might have shared content to.

† Important: note that all log messages are sent with a network request immediately as they occur, and not at the end of the session. We highly recommend that you do not define your console logs (i.e. debug and verbose messages) as info logs. Instead, use Breadcrumbs.

Breadcrumbs

FAQ | API

Other tools limit breadcrumbs via their pricing models, however, we fundamentally believe this is a mistake. Set your low-level debug and verbose messages as Breadcrumbs to provide rich context within each session on the user timeline. Unlike Error, Warning, or Info logs, Breadcrumbs are neither aggregated nor are they sent with properties or a stack trace.

Additionally, breadcrumbs are sent with the session payload and not as they occur. This allows developers to pipe their console logs to provide additional session context without inflating the overall cost of the SDK.

// Add a breadcrumb to the Session Timeline (stack traces and screenshots not applicable)
Embrace.sharedInstance().logBreadcrumb(
                withMessage: "Your 64-char-or-less message here")
// Add a breadcrumb to the User Timeline (stacktraces and screenshots not applicable)
[[Embrace sharedInstance] logBreadcrumbWithMessage:
                 @"Your 64-char-or-less message here"];

Performance Monitoring ("Moments")

FAQ | API

App Moments identify and measure the time to completion of key locations and flows in your app. Conceptually, this is like a stopwatch. SLAs, KPIs, and key experiences are often best measured with Moments. Examples include the time it takes for startups to complete or the time it takes to complete a purchase after a "confirm purchase" button is pressed.

Embrace measures time distributions (durations) and incomplete rates. Incomplete rates fall into three categories:

  1. Abandonment Rates - when a user leaves before the predefined 5s threshold
  2. Stall Rates - when a user leaves after 5s
  3. Crash Rates - when a user crashes or OOMs during the moment.

When defining the start and end(s) of the moment, keep in mind that a moment can have multiple endings (feel free to end it as many times as you like). Similar to log data, moment data is sent immediately when it occurs. We also support adding custom properties to moments with the same 10 property limit as log properties. Pass custom properties to the start and/or end of a moment.

// Moments often end in multiple different places in the app and code.  
// An end event can be called multiple times to ensure a moment is ended.

// Start Moment (allowScreenshot is true by default)
override func viewDidLoad() {
        super.viewDidLoad()
        Embrace.sharedInstance().startMoment(
            withName: "my_view_controller", 
            identifier: "unique moment identifier", //optional
            allowScreenshot: true, //optional
            properties: ["foo": "bar"]) //optional
}
    
// End Moment
override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        Embrace.sharedInstance().endMoment(
        	withName: "my_view_controller", 
          identifier: "unique momnent identifier", // optional
          properties: ["foo": "bar"]) //optional
}
// Start Moment
- (void)viewDidLoad
{
    [super viewDidLoad];
    [[Embrace sharedInstance] startMomentWithName:
        @"my_view_controller" 
        identifier:"unique moment idenfitier"  //optional
        allowScreenshot:YES  //optional
        properties:@{@"foo": @"bar"}];  //optional
}

// End Moment
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [[Embrace sharedInstance] endMomentWithName:@"my_view_controller" 
     identifier:"unique moment idenfitier" // optional
     properties:@{@"foo": @"bar"}]; //optional
}

Moment identifiers are useful when an app has separate parallel instances of the same app Moment. A common use case for parallel moments is around image or photo uploading. Please refer to the FAQ for more on on using moment identifiers.


User Segments ("Personas")

API

Many mobile teams track users in pre-defined segments or cohorts. Often these segments, like payers or heavy bidders, have specific usage patterns with errors that are not detectable or otherwise hidden when aggregated with all other users. Set and clear Personas as soon as you know when a user belongs to or leaves a specific segment.

// Set Persona on a User
Embrace.sharedInstance().setUserPersona("my_persona")

// Clear Persona from User
Embrace.sharedInstance().clearUserPersona("my_persona")
//Set Persona on a User
[[Embrace sharedInstance] setUserPersona:@"my_persona"];

//Clear Persona from User
[[Embrace sharedInstance] clearUserPersona:@"my_persona"];

SDK Config File

Certain SDK configs are only settable in a custom Embrace-Info.plist file that is added to your build targets. The SDK will emit the following log message if the config file is found: Reading config from plist file.

The supported settings are shown below.

Key
Type
Default
Description

API_KEY

string

N/A

You can specify the app ID in the config file instead of specifying it when starting the SDK.

BACKGROUND_FETCH_CAPTURE_ENABLE

bool

false

Control whether background fetch info is captured

CRASH_REPORT_ENABLED

bool

false

Enable the Embrace crash reporter.

NOTE: Only one crash reporter should be enabled at a time. For example, this should not be set to true if you are using Crashlytics.

STARTUP_AUTOEND_SECONDS

integer

N/A

Control whether the startup moment should be automatically ended after a certain number of seconds, if it has not been explicitly ended. This is disabled by default.

STARTUP_MOMENT_SCREENSHOT_ENABLED

bool

true

Control whether screenshots are taken during the startup moment.

TRACE_ID_HEADER_NAME

string

x-emb-trace-id

The name of the header that trace IDs are captured from

WEBVIEW_ENABLE

bool

true

Control whether info for WKWebViews is captured

WEBVIEW_STRIP_QUERYPARAMS

bool

true

Control whether query parameters are captured for WKWebViews

This sample config file shows how you would enable the crash reporter.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CRASH_REPORT_ENABLED</key>
	<true/>
</dict>
</plist>

Integration Guide


iOS Get Started Guide

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.