-
Notifications
You must be signed in to change notification settings - Fork 333
Writing Integrations
Integrations are available to thousands of Segment customers and we have hundreds of integrations in already in our queue, so it's important that you do the following before writing a new integration.
First, you must apply to be a Segment partner.
By working on an integration contribution to Segment, you must agree to the Segment Platform Partners Agreement.
Integrations are decoupled from our core library, hence you are to use whatever structure, IDE, build system, libraries, etc. as you wish. The only requirement is that iOS integrations are written as CocoaPods libraries.
It's recommended that you include your integration as a CocoaPods subspec, so that you can develop your integration in tandem with your library.
You need to provide 2 classes: an integration factory and the integration itself. The integration factory creates an integration from settings provided by Segment. The integration is the layer that receives events form Segment and calls the 3rd party API.
There are three main classes involved in writing an integration:
-
SEGAnalytics
This is the public facing API for our customers. It contains dependencies you might need in your integration, and you can also use it if you are a live streaming root integration that wants to send events back into Segment. -
SEGIntegrationFactory
This class lets the Segment SDK create an instance of yourSEGIntegration
(see below) implementation.
@class SEGAnalytics;
@protocol SEGIntegrationFactory
/**
* Attempts to create an adapter with the given settings. Returns the adapter if one was created, or null
* if this factory isn't capable of creating such an adapter.
*/
-(id<SEGIntegration>) createWithSettings:(NSDictionary *)settings forAnalytics:(SEGAnalytics *)analytics;
/** The key for which this factory can create an Integration. */
-(NSString *)key;
@end
-
SEGIntegration
This is the protocol that you must implement to receive events from the Segment SDK. All methods are optional, so you should only override the ones your SDK needs.
#import <Foundation/Foundation.h>
#import "SEGIdentifyPayload.h"
#import "SEGTrackPayload.h"
#import "SEGScreenPayload.h"
#import "SEGAliasPayload.h"
#import "SEGIdentifyPayload.h"
#import "SEGGroupPayload.h"
@protocol SEGIntegration
@optional
// Identify will be called when the user calls either of the following:
// 1. [[SEGAnalytics sharedInstance] identify:someUserId];
// 2. [[SEGAnalytics sharedInstance] identify:someUserId traits:someTraits];
// 3. [[SEGAnalytics sharedInstance] identify:someUserId traits:someTraits options:someOptions];
// @see https://segment.com/docs/spec/identify/
- (void)identify:(SEGIdentifyPayload *)payload;
// Track will be called when the user calls either of the following:
// 1. [[SEGAnalytics sharedInstance] track:someEvent];
// 2. [[SEGAnalytics sharedInstance] track:someEvent properties:someProperties];
// 3. [[SEGAnalytics sharedInstance] track:someEvent properties:someProperties options:someOptions];
// @see https://segment.com/docs/spec/track/
- (void)track:(SEGTrackPayload *)payload;
// Screen will be called when the user calls either of the following:
// 1. [[SEGAnalytics sharedInstance] screen:someEvent];
// 2. [[SEGAnalytics sharedInstance] screen:someEvent properties:someProperties];
// 3. [[SEGAnalytics sharedInstance] screen:someEvent properties:someProperties options:someOptions];
// @see https://segment.com/docs/spec/screen/
- (void)screen:(SEGScreenPayload *)payload;
// Group will be called when the user calls either of the following:
// 1. [[SEGAnalytics sharedInstance] group:someGroupId];
// 2. [[SEGAnalytics sharedInstance] group:someGroupId traits:];
// 3. [[SEGAnalytics sharedInstance] group:someGroupId traits:someGroupTraits options:someOptions];
// @see https://segment.com/docs/spec/group/
- (void)group:(SEGGroupPayload *)payload;
// Alias will be called when the user calls either of the following:
// 1. [[SEGAnalytics sharedInstance] alias:someNewId];
// 2. [[SEGAnalytics sharedInstance] alias:someNewId options:someOptions];
// @see https://segment.com/docs/spec/alias/
- (void)alias:(SEGAliasPayload *)payload;
// Reset is invoked when the user logs out, and any data saved about the user should be cleared.
- (void)reset;
// Flush is invoked when any queued events should be uploaded.
- (void)flush;
- (void)registerForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken options:(NSDictionary *)options;
// Callbacks for app state changes
// -------------------------------
- (void)applicationDidFinishLaunching:(NSNotification *)notification;
- (void)applicationDidEnterBackground;
- (void)applicationWillEnterForeground;
- (void)applicationWillTerminate;
- (void)applicationWillResignActive;
- (void)applicationDidBecomeActive;
@end
-
SEGPayload
Types These are the distinct payload types, which are semantically equivalent to our spec.
They all extend from the SEGPayload
class, which wraps the context dictionary as defined here: https://segment.com/docs/spec/common/
@interface SEGPayload: NSObject
@property NSDictionary* context;
@property NSDictionary* integrations;
@end
@interface SEGIdentify : SEGPayload
@property NSDictionary* traits;
@end
@interface SEGAlias : SEGPayload
@property NSString* previousId;
@end
@interface SEGGroup : SEGPayload
@property NSString* groupId;
@property NSDictionary* traits;
@end
@interface SEGTrack : SEGPayload
@property NSString* event;
@property NSDictionary* properties;
@end
@interface SEGScreen : SEGPayload
@property NSString* name;
@property NSDictionary* properties;
@end
Our SDK calls methods on these integrations with whatever data our users have provided. You should override the methods you are interested in.
For example, here’s an SDK that only cares about the identify
method.
@implementation EIExampleIntegrationFactory : NSObject<SEGIntegrationFactory>
-(id<SEGIntegration>) createWithSettings:(NSDictionary *)settings forAnalytics:(SEGAnalytics *)analytics
{
return [EIExampleIntegration initWithSettings:settings];
}
-(NSString *)key
{
return @"Example";
}
@end
@implementation EIExampleIntegration: NSObject<SEGIntegration>
-(void)identify:(SEGIdentifyPayload *)payload
{
...
}
@end
For users (or to test out your integration), you should first declare a depndency on the integration in your application Podfile.
pod 'Analytics'
pod 'ExampleIntegration'
Then, register the factory class when you initialize the library.
SEGAnalyticsConfiguration *config = [SEGAnalyticsConfiguration withWriteKey:@"foo"];
[config use:[EIExampleIntegrationFactory singleton]];
[SEGAnalytics setupWithConfiguration:config];