diff --git a/packages/posthog/README.md b/packages/posthog/README.md index 06f1205..ec60493 100644 --- a/packages/posthog/README.md +++ b/packages/posthog/README.md @@ -38,7 +38,7 @@ const alias = async () => { const capture = async () => { await Posthog.capture({ - event: 'test-event', + event: 'event', properties: { key: 'value', }, @@ -49,6 +49,16 @@ const flush = async () => { await Posthog.flush(); }; +const group = async () => { + await Posthog.group({ + type: 'group', + key: 'key', + groupProperties: { + key: 'value', + }, + }); +}; + const identify = async () => { await Posthog.identify({ distinctId: 'distinct-id', @@ -71,7 +81,7 @@ const reset = async () => { const screen = async () => { await Posthog.screen({ - screenTitle: 'test-screen', + screenTitle: 'screen', properties: { key: 'value', }, @@ -99,6 +109,7 @@ const unregister = async () => { * [`alias(...)`](#alias) * [`capture(...)`](#capture) * [`flush()`](#flush) +* [`group(...)`](#group) * [`identify(...)`](#identify) * [`register(...)`](#register) * [`reset()`](#reset) @@ -162,6 +173,23 @@ Only available on Android and iOS. -------------------- +### group(...) + +```typescript +group(options: GroupOptions) => Promise +``` + +Associate the events for that user with a group. + +| Param | Type | +| ------------- | ----------------------------------------------------- | +| **`options`** | GroupOptions | + +**Since:** 6.0.0 + +-------------------- + + ### identify(...) ```typescript @@ -282,6 +310,15 @@ Remove a super property. | **`properties`** | Record<string, any> | The properties to send with the event. | 6.0.0 | +#### GroupOptions + +| Prop | Type | Description | Since | +| --------------------- | ------------------------------------------------------------ | -------------------------------------------- | ----- | +| **`type`** | string | The group type. | 6.0.0 | +| **`key`** | string | The group key. | 6.0.0 | +| **`groupProperties`** | Record<string, any> | The properties to send with the group event. | 6.0.0 | + + #### IdentifyOptions | Prop | Type | Description | Since | @@ -328,9 +365,7 @@ Remove a super property. Construct a type with a set of properties K of type T -{ - [P in K]: T; - } +{ [P in K]: T; } diff --git a/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/Posthog.kt b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/Posthog.kt index 2dbbd8c..fa27c54 100644 --- a/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/Posthog.kt +++ b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/Posthog.kt @@ -8,6 +8,7 @@ import io.capawesome.capacitorjs.plugins.posthog.classes.options.SetupOptions import com.posthog.android.PostHogAndroidConfig import io.capawesome.capacitorjs.plugins.posthog.classes.options.AliasOptions +import io.capawesome.capacitorjs.plugins.posthog.classes.options.GroupOptions import io.capawesome.capacitorjs.plugins.posthog.classes.options.UnregisterOptions class Posthog(private val plugin: PosthogPlugin) { @@ -28,6 +29,14 @@ class Posthog(private val plugin: PosthogPlugin) { com.posthog.PostHog.flush() } + fun group(options: GroupOptions) { + val type = options.type + val key = options.key + val groupProperties = options.groupProperties + + com.posthog.PostHog.group(type = type, key = key, groupProperties = groupProperties) + } + fun identify(options: IdentifyOptions) { val distinctId = options.distinctId val userProperties = options.userProperties diff --git a/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/PosthogPlugin.java b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/PosthogPlugin.java index e77eea8..0ae2e13 100644 --- a/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/PosthogPlugin.java +++ b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/PosthogPlugin.java @@ -8,6 +8,7 @@ import com.getcapacitor.annotation.CapacitorPlugin; import io.capawesome.capacitorjs.plugins.posthog.classes.options.AliasOptions; import io.capawesome.capacitorjs.plugins.posthog.classes.options.CaptureOptions; +import io.capawesome.capacitorjs.plugins.posthog.classes.options.GroupOptions; import io.capawesome.capacitorjs.plugins.posthog.classes.options.IdentifyOptions; import io.capawesome.capacitorjs.plugins.posthog.classes.options.RegisterOptions; import io.capawesome.capacitorjs.plugins.posthog.classes.options.ScreenOptions; @@ -23,6 +24,7 @@ public class PosthogPlugin extends Plugin { private static final String ERROR_DISTINCT_ID_MISSING = "distinctId must be provided."; private static final String ERROR_KEY_MISSING = "key must be provided."; private static final String ERROR_SCREEN_TITLE_MISSING = "screenTitle must be provided."; + private static final String ERROR_TYPE_MISSING = "type must be provided."; private static final String ERROR_VALUE_MISSING = "value must be provided."; private static final String ERROR_UNKNOWN_ERROR = "An unknown error has occurred."; private static final String TAG = "PosthogPlugin"; @@ -85,6 +87,30 @@ public void flush(PluginCall call) { } } + @PluginMethod + public void group(PluginCall call) { + try { + String type = call.getString("type"); + if (type == null) { + call.reject(ERROR_TYPE_MISSING); + return; + } + String key = call.getString("key"); + if (key == null) { + call.reject(ERROR_KEY_MISSING); + return; + } + JSObject groupProperties = call.getObject("groupProperties"); + + GroupOptions options = new GroupOptions(type, key, groupProperties); + + implementation.group(options); + call.resolve(); + } catch (Exception exception) { + rejectCall(call, exception); + } + } + @PluginMethod public void identify(PluginCall call) { try { diff --git a/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/classes/options/GroupOptions.java b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/classes/options/GroupOptions.java new file mode 100644 index 0000000..b396463 --- /dev/null +++ b/packages/posthog/android/src/main/java/io/capawesome/capacitorjs/plugins/posthog/classes/options/GroupOptions.java @@ -0,0 +1,44 @@ +package io.capawesome.capacitorjs.plugins.posthog.classes.options; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.getcapacitor.JSObject; + +import org.json.JSONException; + +import java.util.Map; + +import io.capawesome.capacitorjs.plugins.posthog.PosthogHelper; + +public class GroupOptions { + @NonNull + private String type; + + @NonNull + private String key; + + @Nullable + private Map groupProperties; + + public GroupOptions(@NonNull String type, @NonNull String key, @Nullable JSObject groupProperties) throws JSONException { + this.type = type; + this.key = key; + this.groupProperties = PosthogHelper.createHashMapFromJSONObject(groupProperties); + } + + @NonNull + public String getType() { + return type; + } + + @NonNull + public String getKey() { + return key; + } + + @Nullable + public Map getGroupProperties() { + return groupProperties; + } +} diff --git a/packages/posthog/ios/Plugin.xcodeproj/project.pbxproj b/packages/posthog/ios/Plugin.xcodeproj/project.pbxproj index 65c7e8f..c45aefa 100644 --- a/packages/posthog/ios/Plugin.xcodeproj/project.pbxproj +++ b/packages/posthog/ios/Plugin.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 7C28C8CC2C8AE9CD00271553 /* SetupOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C28C8CB2C8AE9CD00271553 /* SetupOptions.swift */; }; 7C28C8CE2C8AE9D800271553 /* UnregisterOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C28C8CD2C8AE9D800271553 /* UnregisterOptions.swift */; }; 7C28C8D02C8AEA2E00271553 /* PosthogHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C28C8CF2C8AEA2E00271553 /* PosthogHelper.swift */; }; + 7CFD6A9E2C8B046100FF2B17 /* GroupOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFD6A9D2C8B046100FF2B17 /* GroupOptions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -57,6 +58,7 @@ 7C28C8CB2C8AE9CD00271553 /* SetupOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupOptions.swift; sourceTree = ""; }; 7C28C8CD2C8AE9D800271553 /* UnregisterOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnregisterOptions.swift; sourceTree = ""; }; 7C28C8CF2C8AEA2E00271553 /* PosthogHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosthogHelper.swift; sourceTree = ""; }; + 7CFD6A9D2C8B046100FF2B17 /* GroupOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupOptions.swift; sourceTree = ""; }; 91781294A431A2A7CC6EB714 /* Pods-Plugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig"; sourceTree = ""; }; 96ED1B6440D6672E406C8D19 /* Pods-PluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig"; sourceTree = ""; }; F65BB2953ECE002E1EF3E424 /* Pods-PluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig"; sourceTree = ""; }; @@ -146,6 +148,7 @@ 7C28C8C92C8AE9C300271553 /* ScreenOptions.swift */, 7C28C8CB2C8AE9CD00271553 /* SetupOptions.swift */, 7C28C8CD2C8AE9D800271553 /* UnregisterOptions.swift */, + 7CFD6A9D2C8B046100FF2B17 /* GroupOptions.swift */, ); path = Options; sourceTree = ""; @@ -358,6 +361,7 @@ 7C28C8CE2C8AE9D800271553 /* UnregisterOptions.swift in Sources */, 50ADFFA82020EE4F00D50D53 /* PosthogPlugin.m in Sources */, 7C28C8C22C8AE99100271553 /* AliasOptions.swift in Sources */, + 7CFD6A9E2C8B046100FF2B17 /* GroupOptions.swift in Sources */, 7C28C8C42C8AE99E00271553 /* CaptureOptions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/packages/posthog/ios/Plugin/Classes/Options/GroupOptions.swift b/packages/posthog/ios/Plugin/Classes/Options/GroupOptions.swift new file mode 100644 index 0000000..13513ad --- /dev/null +++ b/packages/posthog/ios/Plugin/Classes/Options/GroupOptions.swift @@ -0,0 +1,26 @@ +import Foundation +import Capacitor + +@objc public class GroupOptions: NSObject { + private var type: String + private var key: String + private var groupProperties: [String: Any]? + + init(type: String, key: String, groupProperties: [String: Any]?) { + self.type = type + self.key = key + self.groupProperties = groupProperties + } + + func getType() -> String { + return type + } + + func getKey() -> String { + return key + } + + func getGroupProperties() -> [String: Any]? { + return groupProperties + } +} diff --git a/packages/posthog/ios/Plugin/Posthog.swift b/packages/posthog/ios/Plugin/Posthog.swift index 5c1695f..53fe330 100644 --- a/packages/posthog/ios/Plugin/Posthog.swift +++ b/packages/posthog/ios/Plugin/Posthog.swift @@ -24,6 +24,14 @@ import PostHog @objc public func flush() { PostHogSDK.shared.flush() } + + @objc public func group(_ options: GroupOptions) { + let type = options.getType() + let key = options.getKey() + let groupProperties = options.getGroupProperties() + + PostHogSDK.shared.group(type: type, key: key, groupProperties: groupProperties) + } @objc public func identify(_ options: IdentifyOptions) { let distinctId = options.getDistinctId() diff --git a/packages/posthog/ios/Plugin/PosthogPlugin.m b/packages/posthog/ios/Plugin/PosthogPlugin.m index e08cf18..f1b3d09 100644 --- a/packages/posthog/ios/Plugin/PosthogPlugin.m +++ b/packages/posthog/ios/Plugin/PosthogPlugin.m @@ -7,6 +7,7 @@ CAP_PLUGIN_METHOD(alias, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(capture, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(flush, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(group, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(identify, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(register, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(reset, CAPPluginReturnPromise); diff --git a/packages/posthog/ios/Plugin/PosthogPlugin.swift b/packages/posthog/ios/Plugin/PosthogPlugin.swift index bde8fb1..74e0386 100644 --- a/packages/posthog/ios/Plugin/PosthogPlugin.swift +++ b/packages/posthog/ios/Plugin/PosthogPlugin.swift @@ -14,6 +14,7 @@ public class PosthogPlugin: CAPPlugin { public let errorEventMissing = "event must be provided." public let errorKeyMissing = "key must be provided." public let errorScreenTitleMissing = "screenTitle must be provided." + public let errorTypeMissing = "type must be provided." public let errorValueMissing = "value must be provided." private var implementation: Posthog? @@ -50,6 +51,23 @@ public class PosthogPlugin: CAPPlugin { implementation?.flush() call.resolve() } + + @objc func group(_ call: CAPPluginCall) { + guard let type = call.getString("type") else { + call.reject(errorTypeMissing) + return + } + guard let key = call.getString("key") else { + call.reject(errorKeyMissing) + return + } + let groupProperties = call.getObject("groupProperties") + + let options = GroupOptions(type: type, key: key, groupProperties: groupProperties) + + implementation?.group(options) + call.resolve() + } @objc func identify(_ call: CAPPluginCall) { guard let distinctId = call.getString("distinctId") else { @@ -69,10 +87,15 @@ public class PosthogPlugin: CAPPlugin { call.reject(errorKeyMissing) return } - guard let value = call.getString("value") else { + guard let value = call.getObject("value") as AnyObject? else { call.reject(errorValueMissing) return } + + let options = RegisterOptions(key: key, value: value) + + implementation?.register(options) + call.resolve() } @objc func reset(_ call: CAPPluginCall) { diff --git a/packages/posthog/src/definitions.ts b/packages/posthog/src/definitions.ts index a6d09ab..5e0cfb0 100644 --- a/packages/posthog/src/definitions.ts +++ b/packages/posthog/src/definitions.ts @@ -19,6 +19,12 @@ export interface PosthogPlugin { * @since 6.0.0 */ flush(): Promise; + /** + * Associate the events for that user with a group. + * + * @since 6.0.0 + */ + group(options: GroupOptions): Promise; /** * Identify the current user. * @@ -91,6 +97,32 @@ export interface CaptureOptions { properties?: Record; } +/** + * @since 6.0.0 + */ +export interface GroupOptions { + /** + * The group type. + * + * @since 6.0.0 + * @example 'company' + */ + type: string; + /** + * The group key. + * + * @since 6.0.0 + * @example 'company_id_in_your_db' + */ + key: string; + /** + * The properties to send with the group event. + * + * @since 6.0.0 + */ + groupProperties?: Record; +} + /** * @since 6.0.0 */ diff --git a/packages/posthog/src/web.ts b/packages/posthog/src/web.ts index 0479993..659bcfb 100644 --- a/packages/posthog/src/web.ts +++ b/packages/posthog/src/web.ts @@ -4,6 +4,7 @@ import posthog from 'posthog-js'; import type { AliasOptions, CaptureOptions, + GroupOptions, IdentifyOptions, PosthogPlugin, RegisterOptions, @@ -25,6 +26,10 @@ export class PosthogWeb extends WebPlugin implements PosthogPlugin { this.throwUnimplementedError(); } + async group(options: GroupOptions): Promise { + posthog.group(options.type, options.key, options.groupProperties); + } + async identify(options: IdentifyOptions): Promise { posthog.identify(options.distinctId, options.userProperties); }