diff --git a/Sources/ODP/OdpEventManager.swift b/Sources/ODP/OdpEventManager.swift index d136c6ea..e0df2289 100644 --- a/Sources/ODP/OdpEventManager.swift +++ b/Sources/ODP/OdpEventManager.swift @@ -65,13 +65,20 @@ open class OdpEventManager { func identifyUser(vuid: String?, userId: String?) { var identifiers = [String: String]() - if let _vuid = vuid { - identifiers[Constants.ODP.keyForVuid] = _vuid + if let vuid = vuid, !vuid.isEmpty { + identifiers[Constants.ODP.keyForVuid] = vuid } - if let userId = userId { + if let userId = userId, !userId.isEmpty { identifiers[Constants.ODP.keyForUserId] = userId } - + + // Identify requires 2+ identifiers to link (e.g., vuid + fs_user_id). + // A single identifier has no cross-reference value and generates unnecessary traffic. + guard identifiers.count >= 2 else { + logger.d("ODP identify event is not dispatched (fewer than 2 valid identifiers).") + return + } + sendEvent(type: Constants.ODP.eventType, action: "identified", identifiers: identifiers, diff --git a/Tests/OptimizelyTests-Common/OdpEventManagerTests.swift b/Tests/OptimizelyTests-Common/OdpEventManagerTests.swift index 2f989378..14b85873 100644 --- a/Tests/OptimizelyTests-Common/OdpEventManagerTests.swift +++ b/Tests/OptimizelyTests-Common/OdpEventManagerTests.swift @@ -119,15 +119,11 @@ class OdpEventManagerTests: XCTestCase { validateData(evt.data, customData: [:]) } - func testIdentifyUser_noApiKey_nilUserId() { + func testIdentifyUser_noApiKey_nilUserId_singleIdentifier() { manager.identifyUser(vuid: "v1", userId: nil) - - XCTAssertEqual(1, manager.eventQueue.count) - let evt = manager.eventQueue.getFirstItem()! - XCTAssertEqual("fullstack", evt.type) - XCTAssertEqual("identified", evt.action) - XCTAssertEqual(["vuid": "v1"], evt.identifiers) - validateData(evt.data, customData: [:]) + + // single identifier should be skipped (not queued) + XCTAssertEqual(0, manager.eventQueue.count) } func testSendEvent_apiKey() {