-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Paid events #25
Paid events #25
Changes from 4 commits
5a1a819
3a95801
2b2ab49
fae8d36
b2ae65f
f16983a
6c5f588
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,3 +36,5 @@ Example/Pods | |
|
||
fastlane/* | ||
!fastlane/.env | ||
tests-build/* | ||
test-reports/* |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// PaidEventUserId.swift | ||
// RingPublishingTracking | ||
// | ||
// Created by Bernard Bijoch on 04/09/2024. | ||
// | ||
|
||
import Foundation | ||
|
||
struct PaidEventUserId: Encodable { | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case fakeUserId = "fake_user_id" | ||
case realUserId = "real_user_id" | ||
} | ||
|
||
let fakeUserId: String? | ||
let realUserId: String? | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// | ||
// EventsFactory+Paid.swift | ||
// RingPublishingTracking | ||
// | ||
// Created by Bernard Bijoch on 04/09/2024. | ||
// | ||
|
||
import Foundation | ||
|
||
extension EventsFactory { | ||
|
||
func createPaidEvent(parameters: [String: AnyHashable]) -> Event { | ||
return Event(analyticsSystemName: AnalyticsSystem.kropkaEvents.rawValue, | ||
eventName: EventType.paid.rawValue, | ||
eventParameters: parameters) | ||
} | ||
|
||
func createShowOfferEvent(contentMetadata: ContentMetadata?, | ||
offerData: OfferData, | ||
offerContextData: OfferContextData, | ||
targetPromotionCampaignCode: String?) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "checkout" | ||
parameters[.eventAction] = "showOffer" | ||
parameters[.supplierAppId] = offerData.supplierData.supplierAppId | ||
parameters[.paywallSupplier] = offerData.supplierData.paywallSupplier | ||
parameters[.paywallTemplateId] = offerData.paywallTemplateId | ||
parameters[.displayMode] = offerData.displayMode.rawValue | ||
parameters[.source] = offerContextData.source | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.paywallVariantId] = offerData.paywallVariantId | ||
parameters[.closurePercentage] = offerContextData.closurePercentage | ||
parameters[.tpcc] = targetPromotionCampaignCode | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
func createShowOfferTeaserEvent(contentMetadata: ContentMetadata?, | ||
offerData: OfferData, | ||
offerContextData: OfferContextData, | ||
targetPromotionCampaignCode: String?) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "checkout" | ||
parameters[.eventAction] = "showOfferTeaser" | ||
parameters[.supplierAppId] = offerData.supplierData.supplierAppId | ||
parameters[.paywallSupplier] = offerData.supplierData.paywallSupplier | ||
parameters[.paywallTemplateId] = offerData.paywallTemplateId | ||
parameters[.displayMode] = offerData.displayMode.rawValue | ||
parameters[.source] = offerContextData.source | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.paywallVariantId] = offerData.paywallVariantId | ||
parameters[.closurePercentage] = offerContextData.closurePercentage | ||
parameters[.tpcc] = targetPromotionCampaignCode | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
func createPurchaseClickButtonEvent(contentMetadata: ContentMetadata?, | ||
offerData: OfferData, | ||
offerContextData: OfferContextData, | ||
termId: String, | ||
targetPromotionCampaignCode: String?) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "checkout" | ||
parameters[.eventAction] = "clickButton" | ||
parameters[.supplierAppId] = offerData.supplierData.supplierAppId | ||
parameters[.paywallSupplier] = offerData.supplierData.paywallSupplier | ||
parameters[.paywallTemplateId] = offerData.paywallTemplateId | ||
parameters[.displayMode] = offerData.displayMode.rawValue | ||
parameters[.source] = offerContextData.source | ||
parameters[.termId] = termId | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.paywallVariantId] = offerData.paywallVariantId | ||
parameters[.tpcc] = targetPromotionCampaignCode | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
// swiftlint:disable function_parameter_count | ||
|
||
func createPurchaseEvent(contentMetadata: ContentMetadata?, | ||
offerData: OfferData, | ||
offerContextData: OfferContextData, | ||
subscriptionPaymentData: SubscriptionPaymentData, | ||
termId: String, | ||
termConversionId: String, | ||
targetPromotionCampaignCode: String?, | ||
temporaryUserId: String?) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "checkout" | ||
parameters[.eventAction] = "purchase" | ||
parameters[.supplierAppId] = offerData.supplierData.supplierAppId | ||
parameters[.paywallSupplier] = offerData.supplierData.paywallSupplier | ||
parameters[.paywallTemplateId] = offerData.paywallTemplateId | ||
parameters[.displayMode] = offerData.displayMode.rawValue | ||
parameters[.source] = offerContextData.source | ||
parameters[.termId] = termId | ||
parameters[.termConversionId] = termConversionId | ||
parameters[.paymentMethod] = subscriptionPaymentData.paymentMethod.rawValue | ||
parameters[.subscriptionBasePrice] = subscriptionPaymentData.subscriptionBasePrice | ||
parameters[.subscriptionPriceCurrency] = subscriptionPaymentData.subscriptionPriceCurrency | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.paywallVariantId] = offerData.paywallVariantId | ||
parameters[.tpcc] = targetPromotionCampaignCode | ||
parameters[.subscriptionPromoPrice] = subscriptionPaymentData.subscriptionPromoPrice | ||
parameters[.subscriptionPromoPriceDuration] = subscriptionPaymentData.subscriptionPromoPriceDuration | ||
parameters[.eventDetails] = PaidEventUserId(fakeUserId: temporaryUserId, realUserId: nil).jsonString | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
// swiftlint:enable function_parameter_count | ||
|
||
func createShowMetricLimitEvent(contentMetadata: ContentMetadata?, | ||
supplierData: SupplierData, | ||
metricsData: MetricsData) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "metric_limit" | ||
parameters[.eventAction] = "showMetricLimit" | ||
parameters[.supplierAppId] = supplierData.supplierAppId | ||
parameters[.paywallSupplier] = supplierData.paywallSupplier | ||
parameters[.metricLimitName] = metricsData.metricLimitName | ||
parameters[.freePvCnt] = metricsData.freePageViewCount | ||
parameters[.freePvLimit] = metricsData.freePageViewLimit | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
func createLikelihoodScoringEvent(contentMetadata: ContentMetadata?, | ||
supplierData: SupplierData, | ||
likelihoodData: LikelihoodData) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "likelihood_scoring" | ||
parameters[.eventAction] = "likelihoodScoring" | ||
parameters[.supplierAppId] = supplierData.supplierAppId | ||
parameters[.paywallSupplier] = supplierData.paywallSupplier | ||
parameters[.sourceDx] = contentMetadata?.dxParameter | ||
parameters[.sourcePublicationUuid] = contentMetadata?.publicationId | ||
parameters[.eventDetails] = likelihoodData.jsonString | ||
parameters[.contentMarkedAsPaid] = contentMetadata?.rdlcnParameter | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
func createMobileAppFakeUserIdReplacedEvent(contentMetadata: ContentMetadata?, | ||
temporaryUserId: String, | ||
realUserId: String) -> Event { | ||
var parameters: [PaidEventParameter: AnyHashable] = [:] | ||
|
||
parameters[.eventCategory] = "mobile_app_fake_user_id_replaced" | ||
parameters[.eventAction] = "mobileAppFakeUserIdReplaced" | ||
parameters[.eventDetails] = PaidEventUserId(fakeUserId: temporaryUserId, realUserId: realUserId).jsonString | ||
parameters[.contentMarkedAsPaid] = ContentMarkAsPaid(contentMetadata: contentMetadata)?.jsonStringBase64 | ||
|
||
return createPaidEvent(parameters: parameters.keysAsStrings) | ||
} | ||
|
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// | ||
// Encodable+JSON.swift | ||
// RingPublishingTracking | ||
// | ||
// Created by Bernard Bijoch on 04/09/2024. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Encodable { | ||
|
||
// swiftlint:disable non_optional_string_data_conversion | ||
|
||
var jsonString: String? { | ||
let encoder = JSONEncoder() | ||
encoder.outputFormatting = .sortedKeys | ||
|
||
guard let data = try? encoder.encode(self), | ||
let jsonString = String(data: data, encoding: .utf8) else { return nil } | ||
|
||
return jsonString | ||
} | ||
|
||
// swiftlint:enable non_optional_string_data_conversion | ||
|
||
var jsonStringBase64: String? { | ||
guard let jsonString = jsonString else { return nil } | ||
|
||
return Data(jsonString.utf8).base64EncodedString() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,7 @@ final class KeepAliveManager { | |
private var pauseTimeStart = [Date]() | ||
private var pauseTimeEnd = [Date]() | ||
|
||
private let timerQueue = DispatchQueue(label: "timerQueue", attributes: .concurrent) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To jest fix na testy które na fastlanie nie przechodziły. Timery były uruchamiane z qos: .background. Teraz zrobiłem dedykowaną kolejkę .concurrent |
||
private var measurementTimer: DispatchSourceTimer? | ||
private var sendingTimer: DispatchSourceTimer? | ||
|
||
|
@@ -213,6 +214,25 @@ extension KeepAliveManager { | |
|
||
extension KeepAliveManager { | ||
|
||
/// Schedule timer on dedicated concurrent queue | ||
/// Action is called on main thread | ||
/// | ||
/// - Parameters: | ||
/// - timeInterval: TimeInterval from now when timer should fire | ||
/// - action: (() -> Void)? Action to execute when timer is fired | ||
func scheduledTimer(timeInterval: TimeInterval, action: (() -> Void)?) -> DispatchSourceTimer { | ||
let timer = DispatchSource.makeTimerSource(queue: timerQueue) | ||
timer.setEventHandler { | ||
DispatchQueue.main.async { | ||
action?() | ||
} | ||
} | ||
timer.schedule(deadline: .now() + timeInterval, repeating: .never) | ||
timer.activate() | ||
|
||
return timer | ||
} | ||
|
||
private func scheduleMeasurementTimer() { | ||
guard let timeFromStart = timeFromStart else { | ||
stop() | ||
|
@@ -223,7 +243,7 @@ extension KeepAliveManager { | |
|
||
Logger.log("Keep alive manager: Scheduling measurement timer \(interval)s") | ||
|
||
measurementTimer = DispatchQueue.scheduledTimer(timeInterval: interval, action: { [weak self] in | ||
measurementTimer = scheduledTimer(timeInterval: interval, action: { [weak self] in | ||
self?.takeMeasurements(measureType: .activityTimer) | ||
self?.scheduleMeasurementTimer() | ||
}) | ||
|
@@ -239,7 +259,7 @@ extension KeepAliveManager { | |
|
||
Logger.log("Keep alive manager: Scheduling sending timer \(interval)s") | ||
|
||
sendingTimer = DispatchQueue.scheduledTimer(timeInterval: interval, action: { [weak self] in | ||
sendingTimer = scheduledTimer(timeInterval: interval, action: { [weak self] in | ||
self?.takeMeasurements(measureType: .sendTimer) | ||
self?.sendMeasurements() | ||
self?.scheduleSendingTimer() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to ma tylko sens jak są dwie wartości
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamszeremeta ten obiekt wykorzystywany jest tez przy createPurchaseEvent, gdzie idzie tylko fake_user_id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ale tam ma Bernard to podane jawnie jako
temporaryUserId: String?
bo potem to nie wymusza w tym zdarzeniu z przepisaniem usera podania dwoch wartosci.. chyba ze przez konstruktor to wymusimy a zostanie do uzytku wewnetrznego opcjonalne to ok