@capawesome/capacitor-age-signals¶
Capacitor plugin to use the Play Age Signals API (Android) and DeclaredAgeRange (iOS) to request age signals about the user.
Important Notice
The Play Age Signals API is returning "Not yet implemented" because its live functionality is scheduled to begin on January 1, 2026.
Features¶
We are proud to offer one of the most complete and feature-rich Capacitor plugins for age verification. Here are some of the key features:
- ๐ฅ๏ธ Cross-platform: Supports Android and iOS.
- ๐ Age Verification: Request user age signals using Play Age Signals API (Android) and DeclaredAgeRange (iOS).
- ๐จโ๐ฉโ๐งโ๐ฆ Parental Controls: Support for supervised accounts with parental approval status.
- ๐งช Testing Support: Built-in
FakeAgeSignalsManagerintegration for testing different age verification scenarios (Android). - ๐ Compliance Ready: Built for US state age verification requirements (effective January 1, 2026).
- ๐ฆ SPM: Supports Swift Package Manager for iOS.
- ๐ Up-to-date: Always supports the latest Capacitor version.
Missing a feature? Just open an issue and we'll take a look!
Compatibility¶
| Plugin Version | Capacitor Version | Status |
|---|---|---|
| 0.3.x | >=8.x.x | Active support |
| 0.2.x | 7.x.x | Deprecated |
Installation¶
Android¶
Variables¶
If needed, you can define the following project variable in your app's variables.gradle file to change the default version of the dependency:
$androidPlayAgeSignalsVersionversion ofcom.google.android.play:age-signals(default:0.0.2)
This can be useful if you encounter dependency conflicts with other plugins in your project.
Note: The FakeAgeSignalsManager testing API is included in the main age-signals library, so no additional dependency is required for testing.
iOS¶
Entitlements¶
To use the DeclaredAgeRange API, you must enable the com.apple.developer.declared-age-range entitlement in your app's entitlements file by adding the following key:
Check out the Apple documentation for more information.
Configuration¶
No configuration required for this plugin.
Usage¶
import { AgeSignals } from '@capawesome/capacitor-age-signals';
const checkAgeSignals = async () => {
const result = await AgeSignals.checkAgeSignals();
console.log('User Status:', result.userStatus);
console.log('Age Lower:', result.ageLower);
console.log('Age Upper:', result.ageUpper);
};
const checkEligibility = async () => {
const result = await AgeSignals.checkEligibility();
console.log('Is Eligible:', result.isEligible);
};
Testing¶
The plugin includes support for the FakeAgeSignalsManager API on Android, which allows you to simulate different age signals scenarios in your tests without requiring live responses from Google Play.
Android Testing¶
Important: Due to a known issue in versions 0.0.1 and 0.0.2 of the Age Signals API, you may encounter a java.lang.VerifyError when calling the builder method of AgeSignalsResult in unit tests. As a workaround, run your tests as Android instrumented tests within the androidTest source set.
Example: Testing a Verified Adult User¶
import { AgeSignals, UserStatus } from '@capawesome/capacitor-age-signals';
// Enable the fake manager
await AgeSignals.setUseFakeManager({ useFake: true });
// Set up a verified adult user
await AgeSignals.setNextAgeSignalsResult({
userStatus: UserStatus.Verified,
});
// Check age signals - will return the fake result
const result = await AgeSignals.checkAgeSignals();
console.log(result.userStatus); // 'VERIFIED'
Example: Testing a Supervised User (13-17 years old)¶
import { AgeSignals, UserStatus } from '@capawesome/capacitor-age-signals';
await AgeSignals.setUseFakeManager({ useFake: true });
await AgeSignals.setNextAgeSignalsResult({
userStatus: UserStatus.Supervised,
ageLower: 13,
ageUpper: 17,
installId: 'fake_install_id',
});
const result = await AgeSignals.checkAgeSignals();
console.log(result.userStatus); // 'SUPERVISED'
console.log(result.ageLower); // 13
console.log(result.ageUpper); // 17
console.log(result.installId); // 'fake_install_id'
Example: Testing Parental Approval Scenarios¶
import { AgeSignals, UserStatus } from '@capawesome/capacitor-age-signals';
await AgeSignals.setUseFakeManager({ useFake: true });
// Test pending approval
await AgeSignals.setNextAgeSignalsResult({
userStatus: UserStatus.SupervisedApprovalPending,
ageLower: 13,
ageUpper: 17,
mostRecentApprovalDate: '2025-02-01',
installId: 'fake_install_id',
});
const result = await AgeSignals.checkAgeSignals();
console.log(result.userStatus); // 'SUPERVISED_APPROVAL_PENDING'
console.log(result.mostRecentApprovalDate); // '2025-02-01'
Example: Testing Error Scenarios¶
import { AgeSignals, ErrorCode } from '@capawesome/capacitor-age-signals';
await AgeSignals.setUseFakeManager({ useFake: true });
// Simulate a network error
await AgeSignals.setNextAgeSignalsException({
errorCode: ErrorCode.NetworkError,
});
try {
await AgeSignals.checkAgeSignals();
} catch (error) {
console.log('Caught network error:', error);
}
Disabling the Fake Manager¶
import { AgeSignals } from '@capawesome/capacitor-age-signals';
// Switch back to the production manager
await AgeSignals.setUseFakeManager({ useFake: false });
// This will now use the real Age Signals API
const result = await AgeSignals.checkAgeSignals();
API¶
checkAgeSignals(...)checkEligibility()setUseFakeManager(...)setNextAgeSignalsResult(...)setNextAgeSignalsException(...)- Interfaces
- Enums
checkAgeSignals(...)¶
Request the user's age signals.
| Param | Type |
|---|---|
options |
CheckAgeSignalsOptions |
Returns: Promise<CheckAgeSignalsResult>
Since: 0.0.1
checkEligibility()¶
Check if the user is eligible for age-gated features.
Only available on iOS.
Returns: Promise<CheckEligibilityResult>
Since: 0.3.1
setUseFakeManager(...)¶
Enable or disable the fake age signals manager for testing.
Only available on Android.
| Param | Type |
|---|---|
options |
SetUseFakeManagerOptions |
Since: 0.3.1
setNextAgeSignalsResult(...)¶
Set the next age signals result to be returned by the fake manager.
Only available on Android.
| Param | Type |
|---|---|
options |
SetNextAgeSignalsResultOptions |
Since: 0.3.1
setNextAgeSignalsException(...)¶
Set the next exception to be thrown by the fake manager.
Only available on Android.
| Param | Type |
|---|---|
options |
SetNextAgeSignalsExceptionOptions |
Since: 0.3.1
Interfaces¶
CheckAgeSignalsResult¶
| Prop | Type | Description | Since |
|---|---|---|---|
userStatus |
UserStatus |
The user's verification status. | 0.0.1 |
ageLower |
number |
The (inclusive) lower bound of a supervised user's age range. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED. |
0.0.1 |
ageUpper |
number |
The (inclusive) upper bound of a supervised user's age range. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED and the user's age is under 18. |
0.0.1 |
mostRecentApprovalDate |
string |
The effective from date of the most recent significant change that was approved. When an app is installed, the date of the most recent significant change prior to install is used. Only available when userStatus is SUPERVISED_APPROVAL_PENDING or SUPERVISED_APPROVAL_DENIED. Only available on Android. |
0.0.1 |
installId |
string |
An ID assigned to supervised user installs by Google Play, used for the purposes of notifying you of revoked app approval. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED. Only available on Android. |
0.0.1 |
CheckAgeSignalsOptions¶
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
ageGates |
number[] |
The age ranges that the user falls into. The provided array must contain at least 2 and at most 3 ages. Only available on iOS. | [13, 15, 18] |
0.0.2 |
CheckEligibilityResult¶
| Prop | Type | Description | Since |
|---|---|---|---|
isEligible |
boolean |
Whether the user is eligible for age-gated features. Returns true if the user is in an applicable region that requires additional age-related obligations. Always returns false on macOS. |
0.3.1 |
SetUseFakeManagerOptions¶
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
useFake |
boolean |
Whether to use the fake age signals manager for testing. | false |
0.3.1 |
SetNextAgeSignalsResultOptions¶
| Prop | Type | Description | Since |
|---|---|---|---|
userStatus |
UserStatus |
The user's verification status. | 0.3.1 |
ageLower |
number |
The (inclusive) lower bound of a supervised user's age range. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED. |
0.3.1 |
ageUpper |
number |
The (inclusive) upper bound of a supervised user's age range. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED and the user's age is under 18. |
0.3.1 |
mostRecentApprovalDate |
string |
The effective from date of the most recent significant change that was approved. When an app is installed, the date of the most recent significant change prior to install is used. Only available when userStatus is SUPERVISED_APPROVAL_PENDING or SUPERVISED_APPROVAL_DENIED. |
0.3.1 |
installId |
string |
An ID assigned to supervised user installs by Google Play, used for the purposes of notifying you of revoked app approval. Only available when userStatus is SUPERVISED, SUPERVISED_APPROVAL_PENDING, or SUPERVISED_APPROVAL_DENIED. |
0.3.1 |
SetNextAgeSignalsExceptionOptions¶
| Prop | Type | Description | Since |
|---|---|---|---|
errorCode |
ErrorCode |
The error code to be thrown by the fake manager. | 0.3.1 |
Enums¶
UserStatus¶
| Members | Value | Description | Since |
|---|---|---|---|
Verified |
'VERIFIED' |
The user is over 18. Google verified the user's age using a commercially reasonable method such as a government-issued ID, credit card, or facial age estimation. | 0.0.1 |
Supervised |
'SUPERVISED' |
The user has a supervised Google Account managed by a parent who sets their age. Use ageLower and ageUpper to determine the user's age range. |
0.0.1 |
SupervisedApprovalPending |
'SUPERVISED_APPROVAL_PENDING' |
The user has a supervised Google Account, and their supervising parent has not yet approved one or more pending significant changes. Use ageLower and ageUpper to determine the user's age range. Use mostRecentApprovalDate to determine the last significant change that was approved. |
0.0.1 |
SupervisedApprovalDenied |
'SUPERVISED_APPROVAL_DENIED' |
The user has a supervised Google Account, and their supervising parent denied approval for one or more significant changes. Use ageLower and ageUpper to determine the user's age range. Use mostRecentApprovalDate to determine the last significant change that was approved. |
0.0.1 |
Unknown |
'UNKNOWN' |
The user is not verified or supervised in applicable jurisdictions and regions. These users could be over or under 18. To obtain an age signal from Google Play, ask the user to visit the Play Store to resolve their status. | 0.0.1 |
Empty |
'EMPTY' |
All other users return this value. | 0.0.1 |
ErrorCode¶
| Members | Value | Description | Since |
|---|---|---|---|
ApiNotAvailable |
'API_NOT_AVAILABLE' |
The Play Age Signals API is not available. The Play Store app version installed on the device might be old. | 0.0.1 |
PlayStoreNotFound |
'PLAY_STORE_NOT_FOUND' |
No Play Store app is found on the device. | 0.0.1 |
NetworkError |
'NETWORK_ERROR' |
No available network is found. | 0.0.1 |
PlayServicesNotFound |
'PLAY_SERVICES_NOT_FOUND' |
Play Services is not available or its version is too old. | 0.0.1 |
CannotBindToService |
'CANNOT_BIND_TO_SERVICE' |
Binding to the service in the Play Store has failed. This can be due to having an old Play Store version installed on the device or device memory is overloaded. | 0.0.1 |
PlayStoreVersionOutdated |
'PLAY_STORE_VERSION_OUTDATED' |
The Play Store app needs to be updated. | 0.0.1 |
PlayServicesVersionOutdated |
'PLAY_SERVICES_VERSION_OUTDATED' |
Play Services needs to be updated. | 0.0.1 |
ClientTransientError |
'CLIENT_TRANSIENT_ERROR' |
There was a transient error in the client device. | 0.0.1 |
AppNotOwned |
'APP_NOT_OWNED' |
The app was not installed by Google Play. | 0.0.1 |
InternalError |
'INTERNAL_ERROR' |
Unknown internal error. | 0.0.1 |
Changelog¶
See CHANGELOG.md.
License¶
See LICENSE.