capacitor-google-tag-manager 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapacitorGoogleTagManager.podspec +20 -0
- package/Package.swift +41 -0
- package/README.md +142 -0
- package/android/build.gradle +64 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/kotlin/io/github/maximbelov/googletagmanager/GoogleTagManagerPlugin.kt +34 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +49 -0
- package/dist/esm/definitions.d.ts +26 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +9 -0
- package/dist/esm/web.js +11 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +25 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +28 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/GoogleTagManagerLinkage/GoogleTagManagerLinkage.m +49 -0
- package/ios/Sources/GoogleTagManagerLinkage/include/GoogleTagManagerLinkage.h +8 -0
- package/ios/Sources/GoogleTagManagerPlugin/GoogleTagManagerPlugin.swift +35 -0
- package/ios/Tests/GoogleTagManagerPluginTests/GoogleTagManagerPluginTests.swift +33 -0
- package/package.json +95 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapacitorGoogleTagManager'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.public_header_files = 'ios/Sources/GoogleTagManagerLinkage/include/*.h'
|
|
15
|
+
s.ios.deployment_target = '15.0'
|
|
16
|
+
s.dependency 'Capacitor'
|
|
17
|
+
# Any 9.x from 9.1.0, as in Package.swift. An app pins another one in its Podfile: pod 'GoogleTagManager', '9.3.0'
|
|
18
|
+
s.dependency 'GoogleTagManager', '~> 9.1'
|
|
19
|
+
s.swift_version = '5.9'
|
|
20
|
+
end
|
package/Package.swift
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
// The plugin's job is the dependency on Google's Tag Manager package: an app that installs the plugin gets the SDK linked
|
|
5
|
+
// in, with the Firebase Analytics it depends on. Any 9.x is accepted; the app's Package.resolved records which one it
|
|
6
|
+
// builds with, and the app moves it (Xcode's File > Packages > Update to Latest Package Versions, or an edit of
|
|
7
|
+
// Package.resolved) without a release of this plugin.
|
|
8
|
+
let package = Package(
|
|
9
|
+
name: "CapacitorGoogleTagManager",
|
|
10
|
+
platforms: [.iOS(.v15)],
|
|
11
|
+
products: [
|
|
12
|
+
.library(
|
|
13
|
+
name: "CapacitorGoogleTagManager",
|
|
14
|
+
targets: ["GoogleTagManagerPlugin"])
|
|
15
|
+
],
|
|
16
|
+
dependencies: [
|
|
17
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
|
|
18
|
+
.package(url: "https://github.com/googleanalytics/google-tag-manager-ios-sdk.git", "9.1.0"..<"10.0.0")
|
|
19
|
+
],
|
|
20
|
+
targets: [
|
|
21
|
+
// References the SDK's classes so the linker takes its static archive into the app (see the .m file).
|
|
22
|
+
.target(
|
|
23
|
+
name: "GoogleTagManagerLinkage",
|
|
24
|
+
dependencies: [
|
|
25
|
+
.product(name: "GoogleTagManager", package: "google-tag-manager-ios-sdk")
|
|
26
|
+
],
|
|
27
|
+
path: "ios/Sources/GoogleTagManagerLinkage"),
|
|
28
|
+
.target(
|
|
29
|
+
name: "GoogleTagManagerPlugin",
|
|
30
|
+
dependencies: [
|
|
31
|
+
"GoogleTagManagerLinkage",
|
|
32
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
33
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
34
|
+
],
|
|
35
|
+
path: "ios/Sources/GoogleTagManagerPlugin"),
|
|
36
|
+
.testTarget(
|
|
37
|
+
name: "GoogleTagManagerPluginTests",
|
|
38
|
+
dependencies: ["GoogleTagManagerPlugin"],
|
|
39
|
+
path: "ios/Tests/GoogleTagManagerPluginTests")
|
|
40
|
+
]
|
|
41
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# capacitor-google-tag-manager
|
|
2
|
+
|
|
3
|
+
Brings the [Google Tag Manager](https://developers.google.com/tag-platform/tag-manager) SDK into a Capacitor 8 app, on
|
|
4
|
+
Android and iOS, so that a Tag Manager container the app ships is loaded and acts on the app's Firebase Analytics events.
|
|
5
|
+
|
|
6
|
+
Tag Manager for Firebase has no API to call: once the SDK is linked into the app it finds the container and the Analytics
|
|
7
|
+
events by itself. What it needs from a Capacitor app is to be in the native build, and that is all this plugin does. The
|
|
8
|
+
one method it adds, `isAvailable`, tells from the web view whether the SDK made it into the build, because a build without
|
|
9
|
+
it runs, ships its container and says nothing.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install capacitor-google-tag-manager
|
|
15
|
+
npx cap sync
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requires Capacitor 8, Android 8.0 (API 26) or newer and iOS 15 or newer. The SDK depends on Firebase Analytics, so the app
|
|
19
|
+
needs Firebase set up as usual (for example with `@capacitor-firebase/analytics`); this plugin does not configure it.
|
|
20
|
+
|
|
21
|
+
| Platform | What the plugin adds |
|
|
22
|
+
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| Android | `com.google.android.gms:play-services-tagmanager`, 18.3.0 by default. The SDK's own manifest declares `TagManagerPreviewActivity` with the `tagmanager.c.<application id>` scheme. |
|
|
24
|
+
| iOS | Google's `google-tag-manager-ios-sdk` Swift package, any 9.x from 9.1.0, or the `GoogleTagManager` pod `~> 9.1` with CocoaPods; Firebase Analytics comes with either. |
|
|
25
|
+
| Web | Nothing. A web build that wants Tag Manager loads gtm.js itself; `isAvailable` answers `false`. |
|
|
26
|
+
|
|
27
|
+
### What stays in the app
|
|
28
|
+
|
|
29
|
+
The plugin brings the SDK and nothing that belongs to one app:
|
|
30
|
+
|
|
31
|
+
- **The container.** Export it from Tag Manager and put it where the SDK looks:
|
|
32
|
+
- Android: `android/app/src/main/assets/containers/GTM-XXXXXXX.json`.
|
|
33
|
+
- iOS: a folder reference named `container` in the app target's resources, holding `GTM-XXXXXXX.json`.
|
|
34
|
+
- **The iOS preview scheme.** Tag Manager's preview opens the app through `tagmanager.c.<bundle id>`, which iOS learns
|
|
35
|
+
only from the app's `Info.plist`:
|
|
36
|
+
|
|
37
|
+
```xml
|
|
38
|
+
<key>CFBundleURLTypes</key>
|
|
39
|
+
<array>
|
|
40
|
+
<dict>
|
|
41
|
+
<key>CFBundleURLName</key>
|
|
42
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
43
|
+
<key>CFBundleURLSchemes</key>
|
|
44
|
+
<array>
|
|
45
|
+
<string>tagmanager.c.$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
46
|
+
</array>
|
|
47
|
+
</dict>
|
|
48
|
+
</array>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
On Android nothing is needed: the manifest merge puts the application id into the SDK's own preview activity.
|
|
52
|
+
|
|
53
|
+
### Choosing the SDK version
|
|
54
|
+
|
|
55
|
+
- **Android:** set `playServicesTagManagerVersion` in the app's `android/variables.gradle`:
|
|
56
|
+
|
|
57
|
+
```groovy
|
|
58
|
+
ext {
|
|
59
|
+
playServicesTagManagerVersion = '18.3.0'
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- **iOS, Swift Package Manager:** the plugin accepts any 9.x from 9.1.0, and the version the app builds with is the one in
|
|
64
|
+
its `Package.resolved` (`ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`). Commit that
|
|
65
|
+
file, and move the version with Xcode's File > Packages > Update to Latest Package Versions, or by editing the pin and
|
|
66
|
+
resolving again (`xcodebuild -resolvePackageDependencies`). `npx cap sync` regenerates the app's `CapApp-SPM` package but
|
|
67
|
+
leaves `Package.resolved` alone, so the pin survives a sync.
|
|
68
|
+
- **iOS, CocoaPods:** pin it in the `Podfile`: `pod 'GoogleTagManager', '9.1.0'`.
|
|
69
|
+
|
|
70
|
+
The app should not declare the SDK itself as well: the plugin's declaration is the only one needed.
|
|
71
|
+
|
|
72
|
+
### Why declaring the iOS SDK is not enough
|
|
73
|
+
|
|
74
|
+
Google ships the iOS SDK as a static archive, and an app never calls it: `TAGManager` starts itself from `+load`. A linker
|
|
75
|
+
takes a member of a static archive only when something references a symbol it defines, and Swift Package Manager links
|
|
76
|
+
without `-ObjC`, so an app that merely depends on the package gets the SDK's (empty) framework folder in its bundle and
|
|
77
|
+
none of its code. The plugin's `GoogleTagManagerLinkage` target references every class the SDK exports, which makes the
|
|
78
|
+
linker take them; `isAvailable` then looks each of them up in the running app. CocoaPods links with `-ObjC` and is
|
|
79
|
+
unaffected either way.
|
|
80
|
+
|
|
81
|
+
## Use
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { GoogleTagManager } from 'capacitor-google-tag-manager';
|
|
85
|
+
|
|
86
|
+
const { available } = await GoogleTagManager.isAvailable();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
- `npm test` runs the TypeScript unit tests, `npm run test:parity` checks that both platforms implement exactly the API.
|
|
92
|
+
- `npm run test:android` runs the JVM tests, which also find the SDK on the plugin's class path.
|
|
93
|
+
- `npm run test:ios` runs the XCTest target on an iOS simulator, which also finds the SDK in the test binary.
|
|
94
|
+
- `npm run example:android:build` and `npm run example:ios:build` build `example-app/`, a page that calls `isAvailable`, the
|
|
95
|
+
way an app installs the plugin.
|
|
96
|
+
|
|
97
|
+
## API
|
|
98
|
+
|
|
99
|
+
<docgen-index>
|
|
100
|
+
|
|
101
|
+
* [`isAvailable()`](#isavailable)
|
|
102
|
+
* [Interfaces](#interfaces)
|
|
103
|
+
|
|
104
|
+
</docgen-index>
|
|
105
|
+
|
|
106
|
+
<docgen-api>
|
|
107
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
108
|
+
|
|
109
|
+
The plugin's job is to bring the Google Tag Manager SDK into the app's native build. The SDK then loads the container the
|
|
110
|
+
app ships and acts on Firebase Analytics events by itself; it has no JavaScript API, and neither does this plugin beyond
|
|
111
|
+
the one check below.
|
|
112
|
+
|
|
113
|
+
### isAvailable()
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
isAvailable() => Promise<AvailabilityResult>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Whether the Tag Manager SDK made it into the running app.
|
|
120
|
+
|
|
121
|
+
A build that lost the SDK still runs, ships its container and logs nothing: the container is simply never loaded. This
|
|
122
|
+
is the check that tells such a build apart from a healthy one, from the web view.
|
|
123
|
+
|
|
124
|
+
**Returns:** <code>Promise<<a href="#availabilityresult">AvailabilityResult</a>></code>
|
|
125
|
+
|
|
126
|
+
**Since:** 0.1.0
|
|
127
|
+
|
|
128
|
+
--------------------
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
### Interfaces
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
#### AvailabilityResult
|
|
135
|
+
|
|
136
|
+
What `isAvailable` answers.
|
|
137
|
+
|
|
138
|
+
| Prop | Type | Description |
|
|
139
|
+
| --------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
140
|
+
| **`available`** | <code>boolean</code> | `true` when the Google Tag Manager SDK's classes are in the running app: `TAGManager` on iOS, `com.google.android.gms.tagmanager.TagManagerService` on Android. Always `false` on the web, which has no native SDK. |
|
|
141
|
+
|
|
142
|
+
</docgen-api>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
// The Tag Manager SDK this plugin brings. An app that needs another version sets playServicesTagManagerVersion in its
|
|
4
|
+
// variables.gradle, the way it sets the Capacitor versions; Gradle resolves one version for the whole app either way.
|
|
5
|
+
playServicesTagManagerVersion = project.hasProperty('playServicesTagManagerVersion') ? rootProject.ext.playServicesTagManagerVersion : '18.3.0'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20'
|
|
10
|
+
repositories {
|
|
11
|
+
google()
|
|
12
|
+
mavenCentral()
|
|
13
|
+
}
|
|
14
|
+
dependencies {
|
|
15
|
+
classpath 'com.android.tools.build:gradle:9.5.1'
|
|
16
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
apply plugin: 'com.android.library'
|
|
21
|
+
apply plugin: 'kotlin-android'
|
|
22
|
+
|
|
23
|
+
android {
|
|
24
|
+
namespace = "io.github.maximbelov.googletagmanager"
|
|
25
|
+
compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
|
|
26
|
+
defaultConfig {
|
|
27
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 26
|
|
28
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
|
|
29
|
+
versionCode 1
|
|
30
|
+
versionName "1.0"
|
|
31
|
+
}
|
|
32
|
+
buildTypes {
|
|
33
|
+
release {
|
|
34
|
+
minifyEnabled false
|
|
35
|
+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
lintOptions {
|
|
39
|
+
abortOnError = false
|
|
40
|
+
}
|
|
41
|
+
compileOptions {
|
|
42
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
43
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
kotlin {
|
|
48
|
+
jvmToolchain(21)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
repositories {
|
|
52
|
+
google()
|
|
53
|
+
mavenCentral()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dependencies {
|
|
57
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
58
|
+
implementation project(':capacitor-android')
|
|
59
|
+
// The whole point of the plugin. Its manifest (play-services-tagmanager-api) declares TagManagerService and
|
|
60
|
+
// TagManagerPreviewActivity, the latter with the tagmanager.c.${applicationId} scheme, which the app's manifest merge
|
|
61
|
+
// resolves to the app's own id, so the plugin's manifest repeats neither.
|
|
62
|
+
implementation "com.google.android.gms:play-services-tagmanager:$playServicesTagManagerVersion"
|
|
63
|
+
testImplementation "junit:junit:$junitVersion"
|
|
64
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<!--
|
|
3
|
+
Nothing to declare here. The Tag Manager SDK's own manifest (play-services-tagmanager-api) brings TagManagerService,
|
|
4
|
+
the INTERNET and ACCESS_NETWORK_STATE permissions, and TagManagerPreviewActivity with its
|
|
5
|
+
tagmanager.c.${applicationId} scheme, and the app's manifest merge puts the app's id into that scheme. A second
|
|
6
|
+
declaration of the activity here would only be merged into the same element.
|
|
7
|
+
-->
|
|
8
|
+
</manifest>
|
package/android/src/main/kotlin/io/github/maximbelov/googletagmanager/GoogleTagManagerPlugin.kt
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package io.github.maximbelov.googletagmanager
|
|
2
|
+
|
|
3
|
+
import com.getcapacitor.JSObject
|
|
4
|
+
import com.getcapacitor.Plugin
|
|
5
|
+
import com.getcapacitor.PluginCall
|
|
6
|
+
import com.getcapacitor.PluginMethod
|
|
7
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Google Tag Manager on Android. The plugin exists to put play-services-tagmanager into the app: the SDK finds the
|
|
11
|
+
* container in assets/containers and the Firebase Analytics events on its own, and its manifest brings the preview
|
|
12
|
+
* activity. What is left for the web view is the one question of whether the SDK is there.
|
|
13
|
+
*/
|
|
14
|
+
@CapacitorPlugin(name = "GoogleTagManager")
|
|
15
|
+
class GoogleTagManagerPlugin : Plugin() {
|
|
16
|
+
@PluginMethod
|
|
17
|
+
fun isAvailable(call: PluginCall) {
|
|
18
|
+
call.resolve(JSObject().put("available", TagManagerSdk.isLinked(javaClass.classLoader)))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Whether the Tag Manager SDK's classes are on the app's class path. */
|
|
23
|
+
object TagManagerSdk {
|
|
24
|
+
/** A class the SDK has had since it moved to Google Play services, and the one its manifest names as a service. */
|
|
25
|
+
const val SERVICE_CLASS = "com.google.android.gms.tagmanager.TagManagerService"
|
|
26
|
+
|
|
27
|
+
fun isLinked(loader: ClassLoader?, className: String = SERVICE_CLASS): Boolean =
|
|
28
|
+
try {
|
|
29
|
+
Class.forName(className, false, loader)
|
|
30
|
+
true
|
|
31
|
+
} catch (_: ClassNotFoundException) {
|
|
32
|
+
false
|
|
33
|
+
}
|
|
34
|
+
}
|
|
File without changes
|
package/dist/docs.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"api": {
|
|
3
|
+
"name": "GoogleTagManagerPlugin",
|
|
4
|
+
"slug": "googletagmanagerplugin",
|
|
5
|
+
"docs": "The plugin's job is to bring the Google Tag Manager SDK into the app's native build. The SDK then loads the container the\napp ships and acts on Firebase Analytics events by itself; it has no JavaScript API, and neither does this plugin beyond\nthe one check below.",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"methods": [
|
|
8
|
+
{
|
|
9
|
+
"name": "isAvailable",
|
|
10
|
+
"signature": "() => Promise<AvailabilityResult>",
|
|
11
|
+
"parameters": [],
|
|
12
|
+
"returns": "Promise<AvailabilityResult>",
|
|
13
|
+
"tags": [
|
|
14
|
+
{
|
|
15
|
+
"name": "since",
|
|
16
|
+
"text": "0.1.0"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"docs": "Whether the Tag Manager SDK made it into the running app.\n\nA build that lost the SDK still runs, ships its container and logs nothing: the container is simply never loaded. This\nis the check that tells such a build apart from a healthy one, from the web view.",
|
|
20
|
+
"complexTypes": [
|
|
21
|
+
"AvailabilityResult"
|
|
22
|
+
],
|
|
23
|
+
"slug": "isavailable"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"properties": []
|
|
27
|
+
},
|
|
28
|
+
"interfaces": [
|
|
29
|
+
{
|
|
30
|
+
"name": "AvailabilityResult",
|
|
31
|
+
"slug": "availabilityresult",
|
|
32
|
+
"docs": "What `isAvailable` answers.",
|
|
33
|
+
"tags": [],
|
|
34
|
+
"methods": [],
|
|
35
|
+
"properties": [
|
|
36
|
+
{
|
|
37
|
+
"name": "available",
|
|
38
|
+
"tags": [],
|
|
39
|
+
"docs": "`true` when the Google Tag Manager SDK's classes are in the running app: `TAGManager` on iOS,\n`com.google.android.gms.tagmanager.TagManagerService` on Android. Always `false` on the web, which has no native SDK.",
|
|
40
|
+
"complexTypes": [],
|
|
41
|
+
"type": "boolean"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"enums": [],
|
|
47
|
+
"typeAliases": [],
|
|
48
|
+
"pluginConfigs": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `isAvailable` answers.
|
|
3
|
+
*/
|
|
4
|
+
export interface AvailabilityResult {
|
|
5
|
+
/**
|
|
6
|
+
* `true` when the Google Tag Manager SDK's classes are in the running app: `TAGManager` on iOS,
|
|
7
|
+
* `com.google.android.gms.tagmanager.TagManagerService` on Android. Always `false` on the web, which has no native SDK.
|
|
8
|
+
*/
|
|
9
|
+
available: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The plugin's job is to bring the Google Tag Manager SDK into the app's native build. The SDK then loads the container the
|
|
13
|
+
* app ships and acts on Firebase Analytics events by itself; it has no JavaScript API, and neither does this plugin beyond
|
|
14
|
+
* the one check below.
|
|
15
|
+
*/
|
|
16
|
+
export interface GoogleTagManagerPlugin {
|
|
17
|
+
/**
|
|
18
|
+
* Whether the Tag Manager SDK made it into the running app.
|
|
19
|
+
*
|
|
20
|
+
* A build that lost the SDK still runs, ships its container and logs nothing: the container is simply never loaded. This
|
|
21
|
+
* is the check that tells such a build apart from a healthy one, from the web view.
|
|
22
|
+
*
|
|
23
|
+
* @since 0.1.0
|
|
24
|
+
*/
|
|
25
|
+
isAvailable(): Promise<AvailabilityResult>;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * What `isAvailable` answers.\n */\nexport interface AvailabilityResult {\n /**\n * `true` when the Google Tag Manager SDK's classes are in the running app: `TAGManager` on iOS,\n * `com.google.android.gms.tagmanager.TagManagerService` on Android. Always `false` on the web, which has no native SDK.\n */\n available: boolean;\n}\n\n/**\n * The plugin's job is to bring the Google Tag Manager SDK into the app's native build. The SDK then loads the container the\n * app ships and acts on Firebase Analytics events by itself; it has no JavaScript API, and neither does this plugin beyond\n * the one check below.\n */\nexport interface GoogleTagManagerPlugin {\n /**\n * Whether the Tag Manager SDK made it into the running app.\n *\n * A build that lost the SDK still runs, ships its container and logs nothing: the container is simply never loaded. This\n * is the check that tells such a build apart from a healthy one, from the web view.\n *\n * @since 0.1.0\n */\n isAvailable(): Promise<AvailabilityResult>;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const GoogleTagManager = registerPlugin('GoogleTagManager', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.GoogleTagManagerWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { GoogleTagManager };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,gBAAgB,GAAG,cAAc,CAAyB,kBAAkB,EAAE;IAClF,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;CACpE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { GoogleTagManagerPlugin } from './definitions';\n\nconst GoogleTagManager = registerPlugin<GoogleTagManagerPlugin>('GoogleTagManager', {\n web: () => import('./web').then((m) => new m.GoogleTagManagerWeb()),\n});\n\nexport * from './definitions';\nexport { GoogleTagManager };\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import type { AvailabilityResult, GoogleTagManagerPlugin } from './definitions';
|
|
3
|
+
/**
|
|
4
|
+
* A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.
|
|
5
|
+
* A web build that wants Tag Manager loads gtm.js itself.
|
|
6
|
+
*/
|
|
7
|
+
export declare class GoogleTagManagerWeb extends WebPlugin implements GoogleTagManagerPlugin {
|
|
8
|
+
isAvailable(): Promise<AvailabilityResult>;
|
|
9
|
+
}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
/**
|
|
3
|
+
* A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.
|
|
4
|
+
* A web build that wants Tag Manager loads gtm.js itself.
|
|
5
|
+
*/
|
|
6
|
+
export class GoogleTagManagerWeb extends WebPlugin {
|
|
7
|
+
async isAvailable() {
|
|
8
|
+
return { available: false };
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,KAAK,CAAC,WAAW;QACf,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { AvailabilityResult, GoogleTagManagerPlugin } from './definitions';\n\n/**\n * A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.\n * A web build that wants Tag Manager loads gtm.js itself.\n */\nexport class GoogleTagManagerWeb extends WebPlugin implements GoogleTagManagerPlugin {\n async isAvailable(): Promise<AvailabilityResult> {\n return { available: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const GoogleTagManager = core.registerPlugin('GoogleTagManager', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.GoogleTagManagerWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.
|
|
11
|
+
* A web build that wants Tag Manager loads gtm.js itself.
|
|
12
|
+
*/
|
|
13
|
+
class GoogleTagManagerWeb extends core.WebPlugin {
|
|
14
|
+
async isAvailable() {
|
|
15
|
+
return { available: false };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
20
|
+
__proto__: null,
|
|
21
|
+
GoogleTagManagerWeb: GoogleTagManagerWeb
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
exports.GoogleTagManager = GoogleTagManager;
|
|
25
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst GoogleTagManager = registerPlugin('GoogleTagManager', {\n web: () => import('./web').then((m) => new m.GoogleTagManagerWeb()),\n});\nexport * from './definitions';\nexport { GoogleTagManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/**\n * A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.\n * A web build that wants Tag Manager loads gtm.js itself.\n */\nexport class GoogleTagManagerWeb extends WebPlugin {\n async isAvailable() {\n return { available: false };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;AAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;AACvE,CAAC;;ACFD;AACA;AACA;AACA;AACO,MAAM,mBAAmB,SAASC,cAAS,CAAC;AACnD,IAAI,MAAM,WAAW,GAAG;AACxB,QAAQ,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;AACnC,IAAI;AACJ;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var capacitorGoogleTagManager = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const GoogleTagManager = core.registerPlugin('GoogleTagManager', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.GoogleTagManagerWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.
|
|
10
|
+
* A web build that wants Tag Manager loads gtm.js itself.
|
|
11
|
+
*/
|
|
12
|
+
class GoogleTagManagerWeb extends core.WebPlugin {
|
|
13
|
+
async isAvailable() {
|
|
14
|
+
return { available: false };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
19
|
+
__proto__: null,
|
|
20
|
+
GoogleTagManagerWeb: GoogleTagManagerWeb
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
exports.GoogleTagManager = GoogleTagManager;
|
|
24
|
+
|
|
25
|
+
return exports;
|
|
26
|
+
|
|
27
|
+
})({}, capacitorExports);
|
|
28
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst GoogleTagManager = registerPlugin('GoogleTagManager', {\n web: () => import('./web').then((m) => new m.GoogleTagManagerWeb()),\n});\nexport * from './definitions';\nexport { GoogleTagManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/**\n * A browser has no native Tag Manager SDK, so the answer is `false` rather than an error: the question has an answer here.\n * A web build that wants Tag Manager loads gtm.js itself.\n */\nexport class GoogleTagManagerWeb extends WebPlugin {\n async isAvailable() {\n return { available: false };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;IAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;IACvE,CAAC;;ICFD;IACA;IACA;IACA;IACO,MAAM,mBAAmB,SAASC,cAAS,CAAC;IACnD,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;IACnC,IAAI;IACJ;;;;;;;;;;;"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#import "GoogleTagManagerLinkage.h"
|
|
2
|
+
|
|
3
|
+
// The Tag Manager SDK ships as a static archive, and nothing in an app calls it: TAGManager starts itself from +load and
|
|
4
|
+
// then follows Firebase Analytics. A linker takes an archive member only when something references a symbol it defines,
|
|
5
|
+
// and an app linked without -ObjC (Swift Package Manager adds none) therefore takes none of it. The archive's framework
|
|
6
|
+
// directory still lands in the bundle, so the build looks complete while the SDK, and with it the container, is absent.
|
|
7
|
+
//
|
|
8
|
+
// So every class the archive exports is referenced here. The SDK publishes no headers for them, which is why they are
|
|
9
|
+
// declared below, bare: the declarations only give the compiler a name, and each `[X class]` leaves an undefined
|
|
10
|
+
// `_OBJC_CLASS_$_X` that the linker must resolve from the archive. CocoaPods links with -ObjC anyway; this costs it nothing.
|
|
11
|
+
@interface TAGContainer : NSObject
|
|
12
|
+
@end
|
|
13
|
+
@interface TAGContainerLoader : NSObject
|
|
14
|
+
@end
|
|
15
|
+
@interface TAGDispatchScheduler : NSObject
|
|
16
|
+
@end
|
|
17
|
+
@interface TAGHit : NSObject
|
|
18
|
+
@end
|
|
19
|
+
@interface TAGHitSender : NSObject
|
|
20
|
+
@end
|
|
21
|
+
@interface TAGHitStore : NSObject
|
|
22
|
+
@end
|
|
23
|
+
@interface TAGJSExportedInstructions : NSObject
|
|
24
|
+
@end
|
|
25
|
+
@interface TAGLogger : NSObject
|
|
26
|
+
@end
|
|
27
|
+
@interface TAGManager : NSObject
|
|
28
|
+
@end
|
|
29
|
+
@interface TAGNetReachability : NSObject
|
|
30
|
+
@end
|
|
31
|
+
@interface TAGPendingEvent : NSObject
|
|
32
|
+
@end
|
|
33
|
+
@interface TAGRuntime : NSObject
|
|
34
|
+
@end
|
|
35
|
+
@interface TAGUniversalAnalytics : NSObject
|
|
36
|
+
@end
|
|
37
|
+
|
|
38
|
+
NSArray<NSString *> *GoogleTagManagerLinkedClassNames(void) {
|
|
39
|
+
NSArray<Class> *classes = @[
|
|
40
|
+
[TAGContainer class], [TAGContainerLoader class], [TAGDispatchScheduler class], [TAGHit class], [TAGHitSender class],
|
|
41
|
+
[TAGHitStore class], [TAGJSExportedInstructions class], [TAGLogger class], [TAGManager class],
|
|
42
|
+
[TAGNetReachability class], [TAGPendingEvent class], [TAGRuntime class], [TAGUniversalAnalytics class]
|
|
43
|
+
];
|
|
44
|
+
NSMutableArray<NSString *> *names = [NSMutableArray arrayWithCapacity:classes.count];
|
|
45
|
+
for (Class cls in classes) {
|
|
46
|
+
[names addObject:NSStringFromClass(cls)];
|
|
47
|
+
}
|
|
48
|
+
return names;
|
|
49
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
/// The names of the Tag Manager SDK classes this target links into the app, in the order it references them.
|
|
6
|
+
FOUNDATION_EXPORT NSArray<NSString *> *GoogleTagManagerLinkedClassNames(void);
|
|
7
|
+
|
|
8
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
#if canImport(GoogleTagManagerLinkage)
|
|
4
|
+
import GoogleTagManagerLinkage
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
/// Whether the Tag Manager SDK's classes are in the running app.
|
|
8
|
+
enum TagManagerSdk {
|
|
9
|
+
/// The classes the plugin links in. Calling this is also what keeps the linkage in the binary.
|
|
10
|
+
static var linkedClassNames: [String] {
|
|
11
|
+
GoogleTagManagerLinkedClassNames()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// Asks the Objective-C runtime, by name, for every class the plugin links in, so the answer reflects the binary
|
|
15
|
+
/// that is running rather than what the plugin was compiled against.
|
|
16
|
+
static func isLinked(classNames: [String] = linkedClassNames) -> Bool {
|
|
17
|
+
!classNames.isEmpty && classNames.allSatisfy { NSClassFromString($0) != nil }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Google Tag Manager on iOS. The plugin exists to link the SDK into the app: the SDK finds the container in the app's
|
|
22
|
+
/// `container` folder and the Firebase Analytics events on its own, and handles the `tagmanager.c.<bundle id>` preview
|
|
23
|
+
/// links the app's Info.plist registers. What is left for the web view is the one question of whether the SDK is there.
|
|
24
|
+
@objc(GoogleTagManagerPlugin)
|
|
25
|
+
public class GoogleTagManagerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
26
|
+
public let identifier = "GoogleTagManagerPlugin"
|
|
27
|
+
public let jsName = "GoogleTagManager"
|
|
28
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
29
|
+
CAPPluginMethod(name: "isAvailable", returnType: CAPPluginReturnPromise)
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
@objc func isAvailable(_ call: CAPPluginCall) {
|
|
33
|
+
call.resolve(["available": TagManagerSdk.isLinked()])
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
import Capacitor
|
|
3
|
+
@testable import GoogleTagManagerPlugin
|
|
4
|
+
|
|
5
|
+
/// The JavaScript reaches the plugin by `jsName` and each method by its name: a rename on either side fails only at run
|
|
6
|
+
/// time on a phone, so both are pinned here.
|
|
7
|
+
final class GoogleTagManagerPluginTests: XCTestCase {
|
|
8
|
+
func testIsRegisteredUnderTheNameTheJavaScriptUses() {
|
|
9
|
+
let plugin = GoogleTagManagerPlugin()
|
|
10
|
+
XCTAssertEqual(plugin.jsName, "GoogleTagManager")
|
|
11
|
+
XCTAssertEqual(plugin.identifier, "GoogleTagManagerPlugin")
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func testRegistersExactlyTheMethodsOfTheApi() {
|
|
15
|
+
let names = GoogleTagManagerPlugin().pluginMethods.map(\.name).sorted()
|
|
16
|
+
XCTAssertEqual(names, ["isAvailable"])
|
|
17
|
+
for name in names {
|
|
18
|
+
XCTAssertTrue(GoogleTagManagerPlugin().responds(to: NSSelectorFromString("\(name):")), "no @objc \(name)(_:)")
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// The test bundle links the plugin the way an app does, so the SDK has to be found here: a dependency that is
|
|
23
|
+
/// declared but never reaches the binary fails this rather than a phone.
|
|
24
|
+
func testFindsTheSdkInTheBinary() {
|
|
25
|
+
XCTAssertTrue(TagManagerSdk.linkedClassNames.contains("TAGManager"))
|
|
26
|
+
XCTAssertTrue(TagManagerSdk.isLinked())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func testReportsAClassThatIsNotThereAsMissing() {
|
|
30
|
+
XCTAssertFalse(TagManagerSdk.isLinked(classNames: ["TAGManager", "TAGNoSuchClass"]))
|
|
31
|
+
XCTAssertFalse(TagManagerSdk.isLinked(classNames: []))
|
|
32
|
+
}
|
|
33
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "capacitor-google-tag-manager",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Brings the Google Tag Manager SDK into a Capacitor app on Android and iOS, with its preview activity, so a container shipped with the app is loaded",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Sources",
|
|
14
|
+
"ios/Tests",
|
|
15
|
+
"Package.swift",
|
|
16
|
+
"CapacitorGoogleTagManager.podspec"
|
|
17
|
+
],
|
|
18
|
+
"author": "Maxim Belov",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/MaximBelov/capacitor-google-tag-manager.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/MaximBelov/capacitor-google-tag-manager/issues"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"capacitor",
|
|
29
|
+
"plugin",
|
|
30
|
+
"native",
|
|
31
|
+
"google-tag-manager",
|
|
32
|
+
"gtm",
|
|
33
|
+
"tag-manager",
|
|
34
|
+
"firebase-analytics"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
38
|
+
"verify:ios": "xcodebuild build -scheme CapacitorGoogleTagManager -destination generic/platform=iOS -derivedDataPath build/ios-device",
|
|
39
|
+
"verify:android": "cd android && ./gradlew clean build test",
|
|
40
|
+
"verify:web": "npm run build",
|
|
41
|
+
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
42
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
43
|
+
"eslint": "eslint",
|
|
44
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
45
|
+
"swiftlint": "node-swiftlint",
|
|
46
|
+
"docgen": "docgen --api GoogleTagManagerPlugin --output-readme README.md --output-json dist/docs.json",
|
|
47
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
48
|
+
"clean": "rimraf ./dist",
|
|
49
|
+
"watch": "tsc --watch",
|
|
50
|
+
"prepublishOnly": "npm run build",
|
|
51
|
+
"test": "npm run test:unit",
|
|
52
|
+
"test:unit": "vitest run",
|
|
53
|
+
"test:unit:coverage": "vitest run --coverage",
|
|
54
|
+
"test:parity": "node --test test/unit/platform-parity.test.mjs",
|
|
55
|
+
"test:android": "cd android && ./gradlew test",
|
|
56
|
+
"test:ios": "./scripts/test-ios.sh",
|
|
57
|
+
"example:install": "cd example-app && npm install --no-audit --no-fund",
|
|
58
|
+
"example:android:build": "npm run example:install && cd example-app && npm run build && npx cap sync android && cd android && ./gradlew assembleDebug",
|
|
59
|
+
"example:ios:build": "npm run example:install && cd example-app && npm run build && npx cap sync ios && xcodebuild build -project ios/App/App.xcodeproj -scheme App -destination generic/platform=iOS -derivedDataPath ../build/example-ios CODE_SIGNING_ALLOWED=NO"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@capacitor/android": "^8.0.0",
|
|
63
|
+
"@capacitor/core": "^8.0.0",
|
|
64
|
+
"@capacitor/docgen": "^0.3.1",
|
|
65
|
+
"@capacitor/ios": "^8.0.0",
|
|
66
|
+
"@ionic/eslint-config": "^0.5.0",
|
|
67
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
68
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
69
|
+
"eslint": "^10.14.0",
|
|
70
|
+
"prettier": "^3.6.2",
|
|
71
|
+
"prettier-plugin-java": "^2.7.7",
|
|
72
|
+
"rimraf": "^6.1.0",
|
|
73
|
+
"rollup": "^4.53.2",
|
|
74
|
+
"swiftlint": "^2.0.0",
|
|
75
|
+
"typescript": "~6.0.3",
|
|
76
|
+
"@vitest/coverage-v8": "^5.1.0",
|
|
77
|
+
"vitest": "^5.1.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependencies": {
|
|
80
|
+
"@capacitor/core": ">=8.0.0"
|
|
81
|
+
},
|
|
82
|
+
"prettier": "@ionic/prettier-config",
|
|
83
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
84
|
+
"capacitor": {
|
|
85
|
+
"ios": {
|
|
86
|
+
"src": "ios"
|
|
87
|
+
},
|
|
88
|
+
"android": {
|
|
89
|
+
"src": "android"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"engines": {
|
|
93
|
+
"node": ">=20"
|
|
94
|
+
}
|
|
95
|
+
}
|