Skip to content

Commit

Permalink
Merge pull request #37 from adjust/transaction-ids
Browse files Browse the repository at this point in the history
Add optional parameter transactionId to trackRevenue methods
  • Loading branch information
wellle committed Mar 4, 2014
2 parents 439a8f4 + 5d7cd5a commit e8587b7
Show file tree
Hide file tree
Showing 23 changed files with 197 additions and 82 deletions.
4 changes: 2 additions & 2 deletions Adjust.podspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = "Adjust"
s.version = "3.0.0"
s.version = "3.1.0"
s.summary = "This is the iOS SDK of Adjust. You can read more about it at http://adjust.io."
s.homepage = "http://adjust.io"
s.license = { :type => 'MIT', :file => 'MIT-LICENSE' }
s.author = { "Christian Wellenbrock" => "[email protected]" }
s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v3.0.0" }
s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v3.1.0" }
s.platform = :ios, '4.3'
s.framework = 'AdSupport', 'SystemConfiguration'
s.source_files = 'Adjust/*.{h,m}', 'Adjust/AIAdditions/*.{h,m}'
Expand Down
1 change: 1 addition & 0 deletions Adjust/AIActivityHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
withParameters:(NSDictionary *)parameters;

- (void)trackRevenue:(double)amount
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters;

Expand Down
36 changes: 28 additions & 8 deletions Adjust/AIActivityHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,22 @@ - (void)trackEvent:(NSString *)eventToken
}

- (void)trackRevenue:(double)amount
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
dispatch_async(self.internalQueue, ^{
[self revenueInternal:amount event:eventToken parameters:parameters];
[self revenueInternal:amount transactionId:transactionId event:eventToken parameters:parameters];
});
}

- (void)finishedTrackingWithResponse:(AIResponseData *)response {
if ([self.delegate respondsToSelector:@selector(adjustFinishedTrackingWithResponse:)]) {
[self.delegate performSelectorOnMainThread:@selector(adjustFinishedTrackingWithResponse:)
withObject:response waitUntilDone:NO];
}
}

#pragma mark - internal
- (void)initInternal:(NSString *)yourAppToken {
if (![self checkAppTokenNotNil:yourAppToken]) return;
Expand Down Expand Up @@ -230,13 +238,15 @@ - (void)eventInternal:(NSString *)eventToken
}

- (void)revenueInternal:(double)amount
transactionId:(NSString *)transactionId
event:(NSString *)eventToken
parameters:(NSDictionary *)parameters
{
if (![self checkAppTokenNotNil:self.appToken]) return;
if (![self checkActivityState:self.activityState]) return;
if (![self checkAmount:amount]) return;
if (![self checkEventTokenLength:eventToken]) return;
if (![self checkTransactionId:transactionId]) return;

AIPackageBuilder *revenueBuilder = [[AIPackageBuilder alloc] init];
revenueBuilder.amountInCents = amount;
Expand All @@ -263,13 +273,6 @@ - (void)revenueInternal:(double)amount
[self.logger debug:@"Event %d (revenue)", self.activityState.eventCount];
}

- (void)finishedTrackingWithResponse:(AIResponseData *)response {
if ([self.delegate respondsToSelector:@selector(adjustFinishedTrackingWithResponse:)]) {
[self.delegate performSelectorOnMainThread:@selector(adjustFinishedTrackingWithResponse:)
withObject:response waitUntilDone:NO];
}
}

#pragma mark - private

// returns whether or not the activity state should be written
Expand Down Expand Up @@ -456,4 +459,21 @@ - (BOOL)checkAmount:(double)amount {
return YES;
}

- (BOOL) checkTransactionId:(NSString *)transactionId {
if (transactionId.length == 0) {
return YES; // no transaction ID given
}

if ([self.activityState findTransactionId:transactionId]) {
[self.logger info:@"Skipping duplicate transaction ID '%@'", transactionId];
[self.logger verbose:@"Found transaction ID in %@", self.activityState.transactionIds];
return NO; // transaction ID found -> used already
}

[self.activityState addTransactionId:transactionId];
[self.logger verbose:@"Added transaction ID %@", self.activityState.transactionIds];
// activity state will get written by caller
return YES;
}

@end
8 changes: 4 additions & 4 deletions Adjust/AIActivityKind.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ AIActivityKind AIActivityKindFromString(NSString *string) {

NSString* AIActivityKindToString(AIActivityKind activityKind) {
switch (activityKind) {
case AIActivityKindSession: return @"session"; break;
case AIActivityKindEvent: return @"event"; break;
case AIActivityKindRevenue: return @"revenue"; break;
case AIActivityKindUnknown: return @"unknown"; break;
case AIActivityKindSession: return @"session";
case AIActivityKindEvent: return @"event";
case AIActivityKindRevenue: return @"revenue";
case AIActivityKindUnknown: return @"unknown";
}
}
7 changes: 7 additions & 0 deletions Adjust/AIActivityState.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
@property (nonatomic, assign) double lastActivity; // all times in seconds since 1970
@property (nonatomic, assign) double createdAt;

// last ten transaction identifiers
@property (nonatomic, retain) NSMutableArray *transactionIds;

// not persisted, only injected
@property (nonatomic, assign) double lastInterval;

Expand All @@ -33,4 +36,8 @@
- (void)injectSessionAttributes:(AIPackageBuilder *)packageBilder;
- (void)injectEventAttributes:(AIPackageBuilder *)packageBilder;

// transaction ID management
- (void)addTransactionId:(NSString *)transactionId;
- (BOOL)findTransactionId:(NSString *)transactionId;

@end
41 changes: 33 additions & 8 deletions Adjust/AIActivityState.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#import "UIDevice+AIAdditions.h"


static const int kTransactionIdCount = 10;

#pragma mark public implementation
@implementation AIActivityState

Expand All @@ -29,6 +31,7 @@ - (id)init {
self.lastActivity = -1;
self.createdAt = -1;
self.lastInterval = -1;
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];

return self;
}
Expand All @@ -52,6 +55,22 @@ - (void)injectEventAttributes:(AIPackageBuilder *)builder {
builder.eventCount = self.eventCount;
}

- (void)addTransactionId:(NSString *)transactionId {
if (self.transactionIds == nil) { // create array
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
}

if (self.transactionIds.count == kTransactionIdCount) {
[self.transactionIds removeObjectAtIndex:0]; // make space
}

[self.transactionIds addObject:transactionId]; // add new ID
}

- (BOOL)findTransactionId:(NSString *)transactionId {
return [self.transactionIds containsObject:transactionId];
}

- (NSString *)description {
return [NSString stringWithFormat:@"ec:%d sc:%d ssc:%d sl:%.1f ts:%.1f la:%.1f",
self.eventCount, self.sessionCount, self.subsessionCount, self.sessionLength,
Expand All @@ -72,26 +91,32 @@ - (id)initWithCoder:(NSCoder *)decoder {
self.createdAt = [decoder decodeDoubleForKey:@"createdAt"];
self.lastActivity = [decoder decodeDoubleForKey:@"lastActivity"];
self.uuid = [decoder decodeObjectForKey:@"uuid"];
self.transactionIds = [decoder decodeObjectForKey:@"transactionIds"];

// create UUID for migrating devices
if (self.uuid == nil) {
self.uuid = [UIDevice.currentDevice aiCreateUuid];
}

if (self.transactionIds == nil) {
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
}

self.lastInterval = -1;

return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeInt:self.eventCount forKey:@"eventCount"];
[encoder encodeInt:self.sessionCount forKey:@"sessionCount"];
[encoder encodeInt:self.subsessionCount forKey:@"subsessionCount"];
[encoder encodeDouble:self.sessionLength forKey:@"sessionLength"];
[encoder encodeDouble:self.timeSpent forKey:@"timeSpent"];
[encoder encodeDouble:self.createdAt forKey:@"createdAt"];
[encoder encodeDouble:self.lastActivity forKey:@"lastActivity"];
[encoder encodeObject:self.uuid forKey:@"uuid"];
[encoder encodeInt:self.eventCount forKey:@"eventCount"];
[encoder encodeInt:self.sessionCount forKey:@"sessionCount"];
[encoder encodeInt:self.subsessionCount forKey:@"subsessionCount"];
[encoder encodeDouble:self.sessionLength forKey:@"sessionLength"];
[encoder encodeDouble:self.timeSpent forKey:@"timeSpent"];
[encoder encodeDouble:self.createdAt forKey:@"createdAt"];
[encoder encodeDouble:self.lastActivity forKey:@"lastActivity"];
[encoder encodeObject:self.uuid forKey:@"uuid"];
[encoder encodeObject:self.transactionIds forKey:@"transactionIds"];
}


Expand Down
8 changes: 4 additions & 4 deletions Adjust/AIAdditions/NSString+AIAdditions.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ - (NSString *)aiTrim {

- (NSString *)aiQuote {
if (self == nil) {
return self;
return nil;
}

if ([self rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location != NSNotFound) {
return [NSString stringWithFormat:@"'%@'", self];
if ([self rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location == NSNotFound) {
return self;
}
return self;
return [NSString stringWithFormat:@"'%@'", self];
}

- (NSString *)aiMd5 {
Expand Down
2 changes: 1 addition & 1 deletion Adjust/AIAdjustFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @implementation AIAdjustFactory
if (internalPackageHandler == nil) {
return [AIPackageHandler handlerWithActivityHandler:activityHandler];
}

return [internalPackageHandler initWithActivityHandler:activityHandler];
}

Expand Down
19 changes: 8 additions & 11 deletions Adjust/AIRequestHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,25 @@ - (void)sendInternal:(AIActivityPackage *)package {
if (error != nil) {
AIResponseData *responseData = [AIResponseData dataWithError:error.localizedDescription];
responseData.willRetry = YES;
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.logger error:@"%@. (%@) Will retry later.", package.failureMessage, responseData.error];
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.packageHandler closeFirstPackage];
return;
}

NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];

// wrong status code
if (response.statusCode != 200) {
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
if (response.statusCode == 200) {
// success
responseData.success = YES;
[self.logger info:@"%@", package.successMessage];
} else {
// wrong status code
[self.logger error:@"%@. (%@)", package.failureMessage, responseData.error];
[self.packageHandler sendNextPackage];
return;
}

// success
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];
responseData.success = YES;
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.logger info:@"%@", package.successMessage];
[self.packageHandler sendNextPackage];
}

Expand Down
11 changes: 6 additions & 5 deletions Adjust/AIResponseData.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#pragma mark set by SDK

// the kind of activity (AIActivityKindSession etc.)
// see the AIActivity definition above
// see the AIActivityKind definition
@property (nonatomic, assign) AIActivityKind activityKind;

// true when the activity was tracked successfully
Expand All @@ -45,14 +45,15 @@
// tracker name of current device
@property (nonatomic, copy) NSString *trackerName;

// returns human readable version of activityKind
// (session, event, revenue), see above
- (NSString *)activityKindString;

#pragma mark internals
+ (AIResponseData *)dataWithJsonString:(NSString *)string;
+ (AIResponseData *)dataWithError:(NSString *)error;

- (id)initWithJsonString:(NSString *)string;
- (id)initWithError:(NSString *)error;

// returns human readable version of activityKind
// (session, event, revenue), see above
- (NSString *)activityKindString;

@end
2 changes: 1 addition & 1 deletion Adjust/AIUtil.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <sys/xattr.h>

static NSString * const kBaseUrl = @"https://app.adjust.io";
static NSString * const kClientSdk = @"ios3.0.0";
static NSString * const kClientSdk = @"ios3.1.0";


#pragma mark -
Expand Down
11 changes: 11 additions & 0 deletions Adjust/Adjust.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,25 @@ static NSString * const AIEnvironmentProduction = @"production";
* events have callbacks, you can also pass in parameters that will be
* forwarded to your end point.
*
* A transaction ID can be used to avoid duplicate revenue events. The last ten transaction identifiers are remembered.
* This is useful for in-app purchase tracking where you can pass in the identifier of the reported transaction.
*
* @param amountInCents The amount in cents (example: 1.5 means one and a half cents)
* @param transactionIdentifier The identifier used to avoid duplicate revenue events (optional, see above)
* @param eventToken The token for this revenue event (optional, see above)
* @param parameters Parameters for this revenue event (optional, see above)
*/
+ (void)trackRevenue:(double)amountInCents;
+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken;
+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken withParameters:(NSDictionary *)parameters;

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId;
+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId forEvent:(NSString *)eventToken;
+ (void)trackRevenue:(double)amountInCents
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters;

/**
* Change the verbosity of Adjust's logs.
*
Expand Down
25 changes: 22 additions & 3 deletions Adjust/Adjust.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,37 @@ + (void)trackEvent:(NSString *)eventToken withParameters:(NSDictionary *)paramet
}

+ (void)trackRevenue:(double)amountInCents {
[activityHandler trackRevenue:amountInCents forEvent:nil withParameters:nil];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:nil withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken {
[activityHandler trackRevenue:amountInCents forEvent:eventToken withParameters:nil];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:eventToken withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
[activityHandler trackRevenue:amountInCents forEvent:eventToken withParameters:parameters];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:eventToken withParameters:parameters];
}

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId {
[activityHandler trackRevenue:amountInCents transactionId:transactionId forEvent:nil withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId forEvent:(NSString *)eventToken {
[activityHandler trackRevenue:amountInCents transactionId:transactionId forEvent:eventToken withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
[activityHandler trackRevenue:amountInCents
transactionId:transactionId
forEvent:eventToken
withParameters:parameters];
}

+ (void)setLogLevel:(AILogLevel)logLevel {
Expand Down
Loading

0 comments on commit e8587b7

Please sign in to comment.