diff --git a/cspell.json b/cspell.json
index ae1e2cff180..71467a6a579 100644
--- a/cspell.json
+++ b/cspell.json
@@ -775,6 +775,7 @@
"keystore",
"kibana",
"kill",
+ "kinesisfirehose",
"Kinesis",
"KinesisFirehoseRecorder",
"KinesisRecorder",
diff --git a/public/images/storing-db-creds-in-secrets-manager.png b/public/images/storing-db-creds-in-secrets-manager.png
new file mode 100644
index 00000000000..ba852f45105
Binary files /dev/null and b/public/images/storing-db-creds-in-secrets-manager.png differ
diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs
index af43247e2b8..8b51ded7cd2 100644
--- a/src/directory/directory.mjs
+++ b/src/directory/directory.mjs
@@ -284,10 +284,77 @@ export const directory = {
path: 'src/pages/[platform]/build-a-backend/add-aws-services/in-app-messaging/index.mdx'
},
{
- path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx'
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx',
+ children: [
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/record-events/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/identify-user/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/auto-track-sessions/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/enable-disable/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/streaming-data/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/storing-data/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/personalize-recommendations/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/existing-resources/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/sdk/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/data-usage-policy/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/analytics/app-uninstall/index.mdx'
+ }
+ ]
},
{
path: 'src/pages/[platform]/build-a-backend/add-aws-services/geo/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/index.mdx',
+ children: [
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/set-up-predictions/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/text-to-speech/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/transcribe-audio/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/translate/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-text/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-entity/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/label-image/index.mdx'
+ },
+ {
+ path: 'src/pages/[platform]/build-a-backend/add-aws-services/predictions/interpret-sentiment/index.mdx'
+ }
+ ]
}
]
}
diff --git a/src/fragments/lib/predictions/js/getting-started.mdx b/src/fragments/lib/predictions/js/getting-started.mdx
index 77631421024..c7e4dbf62a9 100644
--- a/src/fragments/lib/predictions/js/getting-started.mdx
+++ b/src/fragments/lib/predictions/js/getting-started.mdx
@@ -92,7 +92,7 @@ Amplify.configure({
identityPoolId: 'us-east-1:xxx-xxx-xxx-xxx-xxx',
region: 'us-east-1'
},
- predictions: {
+ Predictions: {
convert: {
translateText: {
region: 'us-east-1',
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/app-uninstall/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/app-uninstall/index.mdx
new file mode 100644
index 00000000000..237cb7aaa49
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/app-uninstall/index.mdx
@@ -0,0 +1,39 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Uninstalling the app',
+ description:
+ 'Understand how to handle persistent data on a device when a user uninstalls the app.',
+ platforms: ['swift', 'android'],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+Some Amplify categories such as Analytics and Auth persist data to the local device. This application data is removed when a user uninstalls the application from the device.
+
+If the [Android Auto Backup for Apps](https://developer.android.com/guide/topics/data/autobackup) service was enabled, this service will attempt to restore application data.
+
+Amplify Auth uses [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences) when persisting auth data. When an application is uninstalled, the [Android Keystore](https://developer.android.com/training/articles/keystore) keys used to create our EncryptedSharedPreferences files are deleted. Upon an application re-install, these restored files are no longer readable due to the key removal from the Android Keystore.
+
+Due to this limitation with EncryptedSharedPreferences, Auth information can’t be restored on an application re-install. The user will have to re-authenticate.
+
+
+
+Some Amplify categories such as Analytics, Auth, and DataStore persist data to the local device. Some of that data is automatically removed when a user uninstalls the app from the device.
+
+Amplify stores Auth information in the local [system keychain](https://developer.apple.com/documentation/security/keychain_services), which does not guarantee any particular behavior around whether data is removed when an app is uninstalled.
+
+Deciding on when to clear this auth information is not something that the SDK can do in a generic way, so App developers should decide when to clear the data by signing out. One strategy for accomplishing this would be to use [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) to detect whether or not the app is launching for the first time, and invoking [`Auth.signOut()`](/[platform]/build-a-backend/auth/enable-sign-up/#sign-out) if the app has not been launched before.
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/auto-track-sessions/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/auto-track-sessions/index.mdx
new file mode 100644
index 00000000000..32e745d0a6a
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/auto-track-sessions/index.mdx
@@ -0,0 +1,210 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Automatically track sessions',
+ description: 'The Amplify analytics plugin records when an application opens and closes. This session information can be viewed either from your local computer’s terminal or the AWS Console for Pinpoint.',
+ platforms: [
+ 'javascript',
+ 'react-native',
+ 'swift',
+ 'android',
+ 'flutter',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+
+Analytics Auto Tracking helps you to automatically track user behaviors like sessions start/stop, page view change and web events like clicking or mouseover.
+
+## Session Tracking
+
+You can track the session both in a web app or a React Native app by using Analytics. A web session can be defined in different ways. To keep it simple we define a web session as being active when the page is not hidden and inactive when the page is hidden. A session in a React Native app is active when the app is in the foreground and inactive when the app is in the background.
+
+For example:
+
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ // REQUIRED, turn on/off the auto tracking
+ enable: true,
+ // REQUIRED, the event type, it's one of 'event', 'pageView' or 'session'
+ type: 'session',
+ // OPTIONAL, additional options for the tracked event.
+ options: {
+ // OPTIONAL, the attributes of the event
+ attributes: {
+ customizableField: 'attr'
+ }
+ }
+});
+```
+
+By default, when the page/app transitions to the foreground, the Analytics module will send an event to the Amazon Pinpoint Service.
+
+```json
+{
+ "eventType": "_session_start",
+ "attributes": {
+ "customizableField": "attr"
+ }
+}
+```
+
+This behavior can be disabled by calling `configureAutoTrack`:
+
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ enable: false,
+ type: 'session'
+});
+```
+
+## Page View Tracking
+
+Use this feature to track the most frequently viewed page/url in your webapp. It automatically sends events containing url information when a page is visited.
+
+This behavior can be enabled by calling `configureAutoTrack`:
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ // REQUIRED, turn on/off the auto tracking
+ enable: true,
+ // REQUIRED, the event type, it's one of 'event', 'pageView' or 'session'
+ type: 'pageView',
+ // OPTIONAL, additional options for the tracked event.
+ options: {
+ // OPTIONAL, the attributes of the event
+ attributes: {
+ customizableField: 'attr'
+ },
+
+ // OPTIONAL, the event name. By default, this is 'pageView'
+ eventName: 'pageView',
+
+ // OPTIONAL, the type of app under tracking. By default, this is 'multiPageApp'.
+ // You will need to change it to 'singlePage' if your app is a single-page app like React
+ appType: 'multiPageApp',
+
+ // OPTIONAL, provide the URL for the event.
+ urlProvider: () => {
+ // the default function
+ return window.location.origin + window.location.pathname;
+ }
+ }
+});
+```
+
+This behavior can be disabled by calling `configureAutoTrack`:
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ enable: false,
+ type: 'pageView'
+});
+```
+
+## Page Event Tracking
+
+Use this type of tracking to track user interactions with specific elements on a page. Just attach the specified selectors to your DOM element and turn on the auto tracking.
+
+This behavior can be enabled by calling `configureAutoTrack`:
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ // REQUIRED, turn on/off the auto tracking
+ enable: true,
+ // REQUIRED, the event type, it's one of 'event', 'pageView' or 'session'
+ type: 'event',
+ // OPTIONAL, additional options for the tracked event.
+ options: {
+ // OPTIONAL, the attributes of the event
+ attributes: {
+ customizableField: 'attr'
+ },
+ // OPTIONAL, events you want to track. By default, this is 'click'
+ events: ['click'],
+
+ // OPTIONAL, the prefix of the selectors. By default, this is 'data-amplify-analytics-'
+ // Per https://www.w3schools.com/tags/att_global_data.asp, always start
+ // the prefix with 'data' to avoid collisions with the user agent
+ selectorPrefix: 'data-amplify-analytics-'
+ }
+});
+```
+
+For example:
+
+```html
+
+
+```
+
+When the button above is clicked, an event will be sent automatically. This is equivalent to doing:
+
+```html
+
+
+```
+
+This behavior can be disabled by calling `configureAutoTrack`:
+```javascript
+import { configureAutoTrack } from 'aws-amplify/analytics';
+
+configureAutoTrack({
+ enable: false,
+ type: 'event'
+});
+```
+
+
+
+**Note:** Amplify doesn't capture the location automatically. Instead, you can add the location information in the default config when you [configure Analytics](/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/#set-up-existing-analytics-backend) or while [updating the end point](/[platform]/build-a-backend/add-aws-services/analytics/existing-resources).
+
+
+
+
+
+The Amplify analytics plugin records when an application opens and closes. This session information can be viewed either from the AWS Console for Pinpoint.
+
+1. On the Pinpoint Console under **Analytics**, choose **Events**.
+2. Enable filters, you can select `Session Start` and `Session Stop` events to filter on session events.
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/data-usage-policy/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/data-usage-policy/index.mdx
new file mode 100644
index 00000000000..a594ad4a6eb
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/data-usage-policy/index.mdx
@@ -0,0 +1,126 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Data usage policy information',
+ description: "Review the data types gathered by the Amplify library that Apple requires you to disclose in your app's data usage policy when submitting the app to the App Store.",
+ platforms: ['swift'],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+Apple requires app developers to provide the data usage policy of the app when they submit their app to the App Store. See Apple's [User privacy and data use](https://developer.apple.com/app-store/user-privacy-and-data-use/) for more details. Amplify Library is used to interact with AWS resources under the developer’s ownership and management. The library cannot predict the usage of its APIs and it is up to the developer to provide the privacy manifest that accurately reflects the data collected by the app. Below are the different categories identified by Apple and the corresponding data type used by the Amplify Library.
+
+By utilizing the library, Amplify gathers API usage metrics from the AWS services accessed. This process involves adding a user agent to the request made to your AWS service. The user-agent header is included with information about the Amplify Library version, operating system name, and version. AWS collects this data to generate metrics related to our library usage. This information is not linked to the user’s identity and not used for tracking purposes as described in Apple's privacy and data use guidelines.
+
+Should you have any specific concerns or require additional information for the enhancement of your privacy manifest, please don't hesitate to reach out.
+
+## Contact info
+
+| Data Type | Amplify Category | Purpose | Linked To Identity | Tracking | Provided by developer |
+| ------------------------------ | ------------------ | ------------------- | :------------------: | :--------: | :---------------------: |
+| **Name** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ✅ |
+| **Email Address** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ✅ |
+| **Phone Number** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ✅ |
+
+## User Content
+
+| Data Type | Amplify Category | Purpose | Linked To Identity | Tracking | Provided by developer |
+| ------------------------------ | ------------------ | ------------------- | :------------------: | :--------: | :---------------------: |
+| **Photos or Videos** | | | | | |
+| | Storage | App Functionality | ❌ | ❌ | ✅ |
+| | Predictions | App Functionality | ❌ | ❌ | ✅ |
+| **Audio Data** | | | | | |
+| | Predictions | App Functionality | ❌ | ❌ | ✅ |
+
+## Identifiers
+
+| Data Type | Amplify Category | Purpose | Linked To Identity | Tracking | Provided by developer |
+| ------------------------------ | ------------------ | ------------------- | :------------------: | :--------: | :---------------------: |
+| **User ID** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| | Analytics | Analytics | ✅ | ❌ | ❌ |
+| **Device ID** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| | Analytics | Analytics | ✅ | ❌ | ❌ |
+
+## Other Data
+
+| Data Type | Amplify Category | Purpose | Linked To Identity | Tracking | Provided by developer |
+| ------------------------------ | ------------------ | ------------------- | :------------------: | :--------: | :---------------------: |
+| **OS Version** | | | | | |
+| | All categories | Analytics | ❌ | ❌ | ❌ |
+| **OS Name** | | | | | |
+| | All categories | Analytics | ❌ | ❌ | ❌ |
+| **Locale Info** | | | | | |
+| | All categories | Analytics | ❌ | ❌ | ❌ |
+| **App Version** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Min OS target of the app** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Timezone information** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Network information** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Has SIM card** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Cellular Carrier Name** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Device Model** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Device Name** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Device OS Version** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Device Height and Width** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **Device Language** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+| **identifierForVendor** | | | | | |
+| | Auth | App Functionality | ✅ | ❌ | ❌ |
+
+
+## Health and Fitness
+No data is collected
+
+## Financial Info
+No data is collected
+
+## Location
+No data is collected
+
+## Sensitive Info
+No data is collected
+
+## Contacts
+No data is collected
+
+## Browsing History
+No data is collected
+
+## Search History
+No data is collected
+
+## Diagnostics
+No data is collected
+
+
+Some Amplify categories such as Analytics and Auth persist data to the local device. Some of that data is automatically removed when a user uninstalls the app from the device.
+
+Amplify stores Auth information in the local [system keychain](https://developer.apple.com/documentation/security/keychain_services), which does not guarantee any particular behavior around whether data is removed when an app is uninstalled.
+
+Deciding on when to clear this auth information is not something that the SDK can do in a generic way, so App developers should decide when to clear the data by signing out. One strategy for accomplishing this would be to use [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) to detect whether or not the app is launching for the first time, and invoking [`Auth.signOut()`](/[platform]/build-a-backend/auth/enable-sign-up/#sign-out) if the app has not been launched before.
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/enable-disable/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/enable-disable/index.mdx
new file mode 100644
index 00000000000..b25dd2612fe
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/enable-disable/index.mdx
@@ -0,0 +1,131 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Enable and disable analytics',
+ description: 'Learn how to enable/disable analytics using Amplify.',
+ platforms: [
+ 'javascript',
+ 'react-native',
+ 'swift',
+ 'android',
+ 'flutter',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+## Disable Analytics
+
+Analytics is enabled by default when you configure it in your app. To disable Analytics in your app use the `disable` function:
+
+
+```javascript
+import { disable } from 'aws-amplify/analytics';
+
+disable();
+```
+
+
+
+
+
+
+
+```java
+Amplify.Analytics.disable();
+```
+
+
+
+
+```kotlin
+Amplify.Analytics.disable()
+```
+
+
+
+
+```java
+RxAmplify.Analytics.disable();
+```
+
+
+
+
+
+
+```dart
+await Amplify.Analytics.disable();
+```
+
+
+
+```swift
+Amplify.Analytics.disable()
+```
+
+
+## Enable Analytics
+
+To enable analytics you can use the `enable` function in your app:
+
+
+```javascript
+import { enable } from 'aws-amplify/analytics';
+
+enable();
+```
+
+
+
+
+
+
+```java
+Amplify.Analytics.enable();
+```
+
+
+
+
+```kotlin
+Amplify.Analytics.enable()
+```
+
+
+
+
+```java
+RxAmplify.Analytics.enable();
+```
+
+
+
+
+
+
+```dart
+Amplify.Analytics.enable();
+```
+
+
+
+```swift
+Amplify.Analytics.enable()
+```
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/existing-resources/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/existing-resources/index.mdx
new file mode 100644
index 00000000000..72f2004bb23
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/existing-resources/index.mdx
@@ -0,0 +1,169 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Use existing AWS resources',
+ description: 'Configure the Amplify Libraries to use existing Amazon Pinpoint resources by referencing them in your configuration.',
+ platforms: [
+ 'swift',
+ 'android',
+ 'flutter',
+ 'javascript',
+ 'react-native',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+
+## Set up existing analytics backend
+
+The manual setup enables you to use your existing Amazon Pinpoint resource in your app.
+
+```javascript
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: {
+ ...Amplify.getConfig().Analytics,
+ Pinpoint: {
+ // REQUIRED - Amazon Pinpoint App Client ID
+ appId: 'XXXXXXXXXXabcdefghij1234567890ab',
+
+ // REQUIRED - Amazon service region
+ region: 'us-east-1',
+
+ // OPTIONAL - How many events can be buffered at once.
+ bufferSize: 1000,
+
+ // OPTIONAL - How many events will be flushed from the buffer per batch.
+ flushSize: 100,
+
+ // OPTIONAL - The interval in milliseconds to perform a buffer check and flush if necessary.
+ flushInterval: 5000, // 5s
+
+ // OPTIONAL - The limit for failed recording retries.
+ resendLimit: 5
+ }
+ }
+});
+```
+
+## Update your IAM Policy
+
+Amazon Pinpoint service requires an IAM policy in order to use the `record` and `identifyUser` APIs:
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": ["mobiletargeting:UpdateEndpoint", "mobiletargeting:PutEvents"],
+ "Resource": ["arn:aws:mobiletargeting:*::apps/*"]
+ }
+ ]
+}
+```
+
+
+
+
+Existing Amazon Pinpoint resources can be used with the Amplify Libraries by referencing your **Application ID** and **Region** in your `amplifyconfiguration.dart` file.
+
+```dart
+{
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "",
+ "region": ""
+ },
+ "pinpointTargeting": {
+ "region": ""
+ }
+ }
+ }
+ }
+}
+```
+
+- **pinpointAnalytics**
+ - **appId**: Amazon Pinpoint application ID
+ - **region**: AWS Region where the resources are provisioned (e.g. `us-east-1`)
+- **pinpointTargeting**
+ - **region**: AWS Region where the resources are provisioned (e.g. `us-east-1`)
+
+Note that before you can add an AWS resource to your application, the application must have the Amplify libraries installed. If you need to perform this step, see [Install Amplify Libraries](/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/#install-amplify-libraries).
+
+
+
+Existing Amazon Pinpoint resources can be used with the Amplify Libraries by referencing your **Application ID** and **Region** in your `amplifyconfiguration.json` file.
+
+```json
+{
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "",
+ "region": ""
+ }
+ }
+ }
+ }
+}
+```
+
+- **pinpointAnalytics**
+ - **appId**: Amazon Pinpoint application ID
+ - **region**: AWS Region where the resources are provisioned (e.g. `us-east-1`)
+
+Note that before you can add an AWS resource to your application, the application must have the Amplify libraries installed. If you need to perform this step, see [Install Amplify Libraries](/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/#install-amplify-libraries).
+
+
+
+Existing Amazon Pinpoint resources can be used with the Amplify Libraries by referencing your **Application ID** and **Region** in your `amplifyconfiguration.json` file.
+
+```json
+{
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "",
+ "region": ""
+ },
+ "pinpointTargeting": {
+ "region": ""
+ }
+ }
+ }
+ }
+}
+```
+
+- **pinpointAnalytics**
+ - **appId**: Amazon Pinpoint application ID
+ - **region**: AWS Region where the resources are provisioned (e.g. `us-east-1`)
+- **pinpointTargeting**
+ - **region**: AWS Region where the resources are provisioned (e.g. `us-east-1`)
+
+Note that before you can add an AWS resource to your application, the application must have the Amplify libraries installed. If you need to perform this step, see [Install Amplify Libraries](/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/#install-amplify-libraries).
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/identify-user/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/identify-user/index.mdx
new file mode 100644
index 00000000000..591f9f68745
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/identify-user/index.mdx
@@ -0,0 +1,302 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Identify user',
+ description: 'Use the Amplify analytics plugin to inform Pinpoint about your users.',
+ platforms: [
+ 'swift',
+ 'android',
+ 'flutter',
+ 'javascript',
+ 'react-native',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+This call sends information that you have specified about the user to Amazon Pinpoint. This could be for an unauthenticated or an authenticated user.
+
+In addition, `customProperties` and `userAttributes` can also be provided when invoking `identifyUser`. The Amazon Pinpoint console makes that data available as part of the criteria for segment creation. Attributes passed in via `customProperties` will appear under **Custom Endpoint Attributes**, while `userAttributes` will appear under **Custom User Attributes**. See the [Pinpoint documentation](https://docs.aws.amazon.com/pinpoint/latest/userguide/segments-building.html#choosecriteria) for more information on segment creation.
+
+You can get the current user's ID from the Amplify Auth category as shown below. Be sure you have it added and setup per the [Auth category documentation](/[platform]/build-a-backend/auth/set-up-auth/).
+
+If you have asked for location access and received permission, you can also provide that in `UserProfile.Location`.
+
+
+
+
+```java
+UserProfile.Location location = UserProfile.Location.builder()
+ .latitude(47.606209)
+ .longitude(-122.332069)
+ .postalCode("98122")
+ .city("Seattle")
+ .region("WA")
+ .country("USA")
+ .build();
+
+AnalyticsProperties customProperties = AnalyticsProperties.builder()
+ .add("property1", "Property value")
+ .build();
+
+AnalyticsProperties userAttributes = AnalyticsProperties.builder()
+ .add("someUserAttribute", "User attribute value")
+ .build();
+
+AWSPinpointUserProfile profile = AWSPinpointUserProfile.builder()
+ .name("test-user")
+ .email("user@test.com")
+ .plan("test-plan")
+ .location(location)
+ .customProperties(customProperties)
+ .userAttributes(userAttributes)
+ .build();
+
+Amplify.Auth.getCurrentUser(authUser -> {
+ String userId = authUser.getUserId();
+ Amplify.Analytics.identifyUser(userId, profile);
+}, exception -> {
+ Log.e("MyAmplifyApp", "Error getting current user", exception);
+});
+
+
+```
+
+
+
+
+```kotlin
+val location = UserProfile.Location.builder()
+ .latitude(47.606209)
+ .longitude(-122.332069)
+ .postalCode("98122")
+ .city("Seattle")
+ .region("WA")
+ .country("USA")
+ .build();
+
+val customProperties = AnalyticsProperties.builder()
+ .add("property1", "Property value")
+ .build();
+
+val userAttributes = AnalyticsProperties.builder()
+ .add("someUserAttribute", "User attribute value")
+ .build();
+
+val profile = AWSPinpointUserProfile.builder()
+ .name("test-user")
+ .email("user@test.com")
+ .plan("test-plan")
+ .location(location)
+ .customProperties(customProperties)
+ .userAttributes(userAttributes)
+ .build();
+
+Amplify.Auth.getCurrentUser({ authUser ->
+ Amplify.Analytics.identifyUser(authUser.userId, profile);
+}, { exception ->
+ Log.e("MyAmplifyApp", "Error getting current user", exception)
+})
+```
+
+
+
+
+```java
+UserProfile.Location location = UserProfile.Location.builder()
+ .latitude(47.606209)
+ .longitude(-122.332069)
+ .postalCode("98122")
+ .city("Seattle")
+ .region("WA")
+ .country("USA")
+ .build();
+
+AnalyticsProperties customProperties = AnalyticsProperties.builder()
+ .add("property1", "Property value")
+ .build();
+
+AnalyticsProperties userAttributes = AnalyticsProperties.builder()
+ .add("someUserAttribute", "User attribute value")
+ .build();
+
+AWSPinpointUserProfile profile = AWSPinpointUserProfile.builder()
+ .name("test-user")
+ .email("user@test.com")
+ .plan("test-plan")
+ .location(location)
+ .customProperties(customProperties)
+ .userAttributes(userAttributes)
+ .build();
+
+RxAmplify.Auth.getCurrentUser()
+ .subscribe(
+ result -> {
+ String userId = result.getUserId();
+ RxAmplify.Analytics.identifyUser(userId, profile);
+ },
+ error -> Log.e("AuthQuickStart", error.toString())
+ );
+```
+
+
+
+
+
+
+This call sends information about the current user (which could be unauthenticated or authenticated) to Amazon Pinpoint.
+
+You can provide `name`, `email` and `plan`, as well as location information with `AnalyticsUserProfile.Location`. You can also send additional custom attributes using `AnalyticsProperties`.
+
+If the user is signed in through [Amplify.Auth.signIn](/[platform]/build-a-backend/auth/enable-sign-up/#sign-in), then you can retrieve the current user's ID as shown below:
+
+```swift
+
+let user = try await Amplify.Auth.getCurrentUser()
+
+let location = AnalyticsUserProfile.Location(
+ latitude: 47.606209,
+ longitude: -122.332069,
+ postalCode: "98122",
+ city: "Seattle",
+ region: "WA",
+ country: "USA"
+)
+
+let properties: AnalyticsProperties = [
+ "phoneNumber": "+11234567890",
+ "age": 25
+]
+
+let userProfile = AnalyticsUserProfile(
+ name: "username",
+ email: "name@example.com",
+ plan: "plan",
+ location: location,
+ properties: properties
+)
+
+Amplify.Analytics.identifyUser(
+ userId: user.userId,
+ userProfile: userProfile
+)
+```
+
+
+
+This call sends information that you have specified about a user to Amazon Pinpoint. This could be for an unauthenticated (guest) or an authenticated user.
+
+You can get the current user's ID from the Amplify Auth category as shown per the Auth category documentation. Be sure to have it ready before you set it as shown below (Check out the [Authentication Getting Started](/[platform]/build-a-backend/auth/set-up-auth/) guide for detailed explanation).
+
+If you have asked for location access and received permission, you can also provide that in `UserProfileLocation`
+
+
+
+Breaking changes from v0 to v1:
+
+The Analytics- prefix of the original `AnalyticsUserProfile` and `AnalyticsUserProfileLocation` classes is removed. Furthermore, `AnalyticsProperties` is renamed to `CustomProperties`.
+
+
+
+
+```dart
+Future addAnalyticsWithLocation({
+ required String userId,
+ required String name,
+ required String email,
+ required String phoneNumber,
+ required int age,
+}) async {
+ final userProfile = UserProfile(
+ name: name,
+ email: email,
+ location: const UserProfileLocation(
+ latitude: 47.606209,
+ longitude: -122.332069,
+ postalCode: '98122',
+ city: 'Seattle',
+ region: 'WA',
+ country: 'USA',
+ ),
+ customProperties: CustomProperties()
+ ..addStringProperty('phoneNumber', phoneNumber)
+ ..addIntProperty('age', age),
+ );
+
+ await Amplify.Analytics.identifyUser(
+ userId: userId,
+ userProfile: userProfile,
+ );
+}
+```
+
+
+
+
+This API sends information about the current user to Amazon Pinpoint.
+
+Additional information such as the user's name, email, location, and device can be included by specifying the `UserProfile`. Custom attributes can also be included by setting `UserProfile.customProperties`.
+
+If the user was signed in through [signIn](/[platform]/prev/build-a-backend/auth/enable-sign-up/) you can retrieve the current user's ID as shown below:
+
+```js
+import { identifyUser } from 'aws-amplify/analytics';
+import { getCurrentUser } from 'aws-amplify/auth';
+
+const location = {
+ latitude: 47.606209,
+ longitude: -122.332069,
+ postalCode: '98122',
+ city: 'Seattle',
+ region: 'WA',
+ country: 'USA'
+};
+
+const customProperties = {
+ plan: ['plan'],
+ phoneNumber: ['+11234567890'],
+ age: ['25']
+};
+
+const userProfile = {
+ location,
+ name: 'username',
+ email: 'name@example.com',
+ customProperties
+};
+
+async function sendUserData() {
+ const user = await getCurrentUser();
+
+ identifyUser({
+ userId: user.userId,
+ userProfile
+ });
+}
+```
+
+
+
+Sending user information allows you to associate a user to their user profile and activities or actions in your app. The user's actions and attributes can also tracked across devices and platforms by using the same `userId`.
+
+Some scenarios for identifying a user and their associated app activities are:
+* When a user completes app sign up
+* When a user completes sign in process
+* When a user launches your app
+* When a user modifies or updates their user profile
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx
index a9a92f029f0..677d30bb14b 100644
--- a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/index.mdx
@@ -1,17 +1,19 @@
+import { getChildPageNodes } from '@/utils/getChildPageNodes';
import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
export const meta = {
title: 'Analytics',
description: 'Learn how to set Analytics resource powered by Pinpoint',
+ route: "/[platform]/build-a-backend/add-aws-services/analytics",
platforms: [
+ 'javascript',
+ 'react-native',
+ 'swift',
'android',
- 'angular',
'flutter',
- 'javascript',
+ 'angular',
'nextjs',
'react',
- 'react-native',
- 'swift',
'vue'
]
};
@@ -21,73 +23,13 @@ export const getStaticPaths = async () => {
};
export function getStaticProps(context) {
+ const childPageNodes = getChildPageNodes(meta.route);
return {
props: {
- meta
+ meta,
+ childPageNodes
}
};
}
-
-
-**Under active development:** The `addOutput` method for Amplify Gen 2 is under active development. The experience may change between versions of `@aws-amplify/backend`. Try it out and provide feedback at https://github.com/aws-amplify/amplify-backend/issues/new/choose
-
-
-
-Amplify enables you to collect analytics data for your app. The Analytics category uses Amazon Cognito Identity pools to _identify_ users in your app.
-The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create the an Analytics resource powered by [Amazon Pinpoint](https://aws.amazon.com/pinpoint/).
-
-```ts title="amplify/backend.ts"
-import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
-import { CfnApp } from "aws-cdk-lib/aws-pinpoint";
-
-const backend = defineBackend({
- auth,
- data,
- // additional resources
-});
-
-const analyticsStack = backend.createStack("analytics-stack");
-
-// create a Pinpoint app
-const pinpoint = new CfnApp(analyticsStack, "Pinpoint", {
- name: "myPinpointApp",
-});
-
-// create an IAM policy to allow interacting with Pinpoint
-const pinpointPolicy = new Policy(analyticsStack, "PinpointPolicy", {
- policyName: "PinpointPolicy",
- statements: [
- new PolicyStatement({
- actions: ["mobiletargeting:UpdateEndpoint", "mobiletargeting:PutEvents"],
- resources: [pinpoint.attrArn + "/*"],
- }),
- ],
-});
-
-// apply the policy to the authenticated and unauthenticated roles
-backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(pinpointPolicy);
-backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(pinpointPolicy);
-
-// patch the custom Pinpoint resource to the expected output configuration
-backend.addOutput({
- Analytics: {
- AWSPinpoint: {
- appId: pinpoint.ref,
- region: Stack.of(pinpoint).region,
- },
- },
-});
-```
-
-### Initialize Analytics
-
-To initialize Analytics you need to configure Amplify with `Amplify.configure()`
-
-### Working with Analytics
-
-Refer to the [Analytics documentation](/gen1/[platform]/build-a-backend/more-features/analytics/) to learn how to track events and user sessions in your app.
-
-### References
-
-[Amazon Pinpoint Construct Library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_pinpoint-readme.html)
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/personalize-recommendations/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/personalize-recommendations/index.mdx
new file mode 100644
index 00000000000..55167ee105f
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/personalize-recommendations/index.mdx
@@ -0,0 +1,133 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Personalized recommendations',
+ description: 'Amazon Personalize can create recommendations by using event data, historical data, or a combination of both. The event data can then be used to create recommendations.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue',
+ "react-native",
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+Amazon Personalize can create recommendations by using event data, historical data, or a combination of both. The event data can then be used to create recommendations.
+
+To record event data, you need the following:
+
+* [A dataset group](https://docs.aws.amazon.com/personalize/latest/dg/data-prep-ds-group.html)
+* [An event tracker](https://docs.aws.amazon.com/personalize/latest/dg/event-get-tracker.html).
+
+For more information, see [Record Events](https://docs.aws.amazon.com/personalize/latest/dg/recording-events.html).
+
+### Installation and Configuration
+
+After creating the Amazon Personalize dataset group, you need to add the `personalize:PutEvents` permission to your Amplify IAM user roles.
+
+An example IAM policy:
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": "personalize:PutEvents",
+ "Resource": "arn:aws:personalize:::event-tracker/"
+ }]
+}
+```
+
+You need the tracking ID of your event tracker. For more information, see [Get a Tracking ID](https://docs.aws.amazon.com/personalize/latest/dg/action-interaction-tracker-id.html).
+
+Configure Amazon Personalize:
+
+```javascript
+import { Amplify } from 'aws-amplify';
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: {
+ Personalize: {
+ // REQUIRED - The trackingId to track the events
+ trackingId: '',
+ // REQUIRED - Amazon Personalize service region
+ region: 'us-east-1',
+ // OPTIONAL - The number of events to be deleted from the buffer when flushed.
+ flushSize: 10,
+ // OPTIONAL - The interval in milliseconds to perform a buffer check and flush if necessary.
+ flushInterval: 5000 // 5s
+ }
+ }
+});
+```
+### Working with the API
+
+You can use the `Identify` event type to track a user identity. This lets you connect a user to their actions and record traits about them. To identify a user, specify a unique identifier for the userId property.
+ Consider the following user interactions when choosing when and how often to call record with the Identify eventType:
+
+* After a user registers.
+* After a user logs in.
+* When a user updates their information (For example, changing or adding a new address).
+* Upon loading any pages that are accessible by a logged-in user (optional).
+
+```javascript
+import { record } from 'aws-amplify/analytics/personalize';
+
+record({
+ eventType: 'Identify',
+ properties: {
+ userId: ''
+ }
+});
+```
+You can send events to Amazon personalize by calling the `record` operation. If you already use `Identify` to track end-user data, you can skip the userId, the SDK will fetch the userId based on current browser session.
+For information about the properties field, see [Put Events](https://docs.aws.amazon.com/personalize/latest/dg/API_UBS_PutEvents.html).
+
+```javascript
+import { record } from 'aws-amplify/analytics/personalize';
+
+record({
+ eventType: '',
+ userId: '', // optional
+ properties: {
+ itemId: '',
+ eventValue: ''
+ }
+});
+```
+You can track iframe and HTML5 media types by using the MediaAutoTrack event type. MediaAutoTrack tracks all media events of the media DOM element that you bind to. `MediaAutoTracker` will automatically track *Play*, *Pause*, *Ended*, *TimeWatched*, and *Resume* in `eventType`. The duration of the event compared to the total length of the media is stored as a percentage value in `eventValue`.
+
+```javascript
+import { record } from 'aws-amplify/analytics/personalize';
+
+record({
+ eventType: 'MediaAutoTrack',
+ userId: '', // (optional)
+ properties: {
+ domElementId: 'media-dom-element-id',
+ itemId: ''
+ }
+});
+```
+
+## Flush events
+The recorded events are saved in a buffer and sent to the remote server periodically *(You can tune it with the `flushInterval` option)*. If needed, you have the option to manually clear all the events from the buffer by using the 'flushEvents' API.
+
+```javascript
+import { flushEvents } from 'aws-amplify/analytics/personalize';
+
+flushEvents();
+```
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/record-events/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/record-events/index.mdx
new file mode 100644
index 00000000000..6f8b02af202
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/record-events/index.mdx
@@ -0,0 +1,587 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Record events',
+ description: 'Learn how to record analytics events using Amplify.',
+ platforms: [
+ 'javascript',
+ 'react-native',
+ 'swift',
+ 'android',
+ 'flutter',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+## Record event
+
+The Amplify analytics plugin also makes it easy to record custom events within the app. The plugin handles retry logic in the event the device loses network connectivity and automatically batches requests to reduce network bandwidth.
+
+
+
+
+```java
+AnalyticsEvent event = AnalyticsEvent.builder()
+ .name("PasswordReset")
+ .addProperty("Channel", "SMS")
+ .addProperty("Successful", true)
+ .addProperty("ProcessDuration", 792)
+ .addProperty("UserAge", 120.3)
+ .build();
+
+Amplify.Analytics.recordEvent(event);
+```
+
+
+
+
+```kotlin
+val event = AnalyticsEvent.builder()
+ .name("PasswordReset")
+ .addProperty("Channel", "SMS")
+ .addProperty("Successful", true)
+ .addProperty("ProcessDuration", 792)
+ .addProperty("UserAge", 120.3)
+ .build()
+
+Amplify.Analytics.recordEvent(event)
+```
+
+
+
+
+```java
+AnalyticsEvent event = AnalyticsEvent.builder()
+ .name("PasswordReset")
+ .addProperty("Channel", "SMS")
+ .addProperty("Successful", true)
+ .addProperty("ProcessDuration", 792)
+ .addProperty("UserAge", 120.3)
+ .build();
+
+RxAmplify.Analytics.recordEvent(event);
+```
+
+
+
+
+
+
+The AWS Pinpoint event count updates in minutes after recording your event.
+
+However, it can take upwards of 30 minutes for the event to display in the Filter section, and for its custom attributes to appear in Pinpoint.
+
+
+
+## Flush events
+
+Events have default configuration to flush out to the network every 30 seconds. If you would like to change this, update `amplifyconfiguration.json` with the value in milliseconds you would like for `autoFlushEventsInterval`. This configuration will flush events every 10 seconds:
+
+```json
+{
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "AppID",
+ "region": "Region",
+ "autoFlushEventsInterval": 10000
+ },
+ "pinpointTargeting": {
+ "region": "Region"
+ }
+ }
+ }
+ }
+}
+```
+
+To manually flush events, call:
+
+
+
+
+```java
+Amplify.Analytics.flushEvents();
+```
+
+
+
+
+```kotlin
+Amplify.Analytics.flushEvents()
+```
+
+
+
+
+```java
+RxAmplify.Analytics.flushEvents();
+```
+
+
+
+
+When flushing events, a [Hub event](/[platform]/build-a-backend/utilities/hub/) is sent containing the events which were successfully sent to the Pinpoint service. To receive a list of these events, subscribe to the `HubChannel.ANALYTICS` channel and handle an event of the type `AnalyticsChannelEventName.FLUSH_EVENTS`.
+
+## Authentication events
+
+Indicate how frequently users authenticate with your application.
+
+On the **Analytics** page, the **Users** tab displays charts for **Sign-ins, Sign-ups, and Authentication failures**.
+
+To learn how frequently users authenticate with your app, update your application code so that Pinpoint receives the following standard event types for authentication:
+
+ - `_userauth.sign_in`
+ - `_userauth.sign_up`
+ - `_userauth.auth_fail`
+
+You can report authentication events by doing either of the following:
+
+ - Managing user sign-up and sign-in with Amazon Cognito user pools.
+
+ Cognito user pools are user directories that make it easier to add sign-up and sign-in to your app. As users authenticate with your app, Cognito reports authentication events to Pinpoint. For more information, see [Using Amazon Pinpoint Analytics with Amazon Cognito User Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-pinpoint-integration.html) in the _Amazon Cognito Developer Guide_. Also update **amplifyconfiguration.json** by adding the `PinpointAppId` key under `CognitoUserPool`.
+
+ ```json
+ "CognitoUserPool": {
+ "Default": {
+ "PoolId": "",
+ "AppClientId": "",
+ "Region": "",
+ "PinpointAppId": ""
+ }
+ }
+ ```
+
+- Manually recording events using the `recordEvent()` API.
+
+ If you don't want to use Cognito user pools, you can use the Pinpoint client to record and submit authentication events, as shown in the following examples. In these examples, the event type is set to `_userauth.sign_in`, but you can substitute any authentication event type.
+
+
+
+
+ ```java
+ /**
+ * Call this method to log an authentication event to the analytics client.
+ */
+ public void logAuthenticationEvent() {
+ AnalyticsEvent event = AnalyticsEvent.builder()
+ .name("_userauth.sign_in")
+ .build();
+ Amplify.Analytics.recordEvent(event);
+ }
+ ```
+
+
+
+
+ ```kotlin
+
+ /**
+ * Call this method to log an authentication event to the analytics client.
+ */
+ fun logAuthenticationEvent() {
+ val event = AnalyticsEvent.builder()
+ .name("_userauth.sign_in")
+ .build()
+ Amplify.Analytics.recordEvent(event)
+ }
+ ```
+
+
+
+ ```java
+
+ /**
+ * Call this method to log an authentication event to the analytics client.
+ */
+ public void logAuthenticationEvent() {
+ AnalyticsEvent event = AnalyticsEvent.builder()
+ .name("_userauth.sign_in")
+ .build();
+ RxAmplify.Analytics.recordEvent(event);
+ }
+ ```
+
+
+
+## Global Properties
+
+You can register global properties which will be sent along with all invocations of `Amplify.Analytics.recordEvent`.
+
+
+
+
+```java
+Amplify.Analytics.registerGlobalProperties(
+ AnalyticsProperties.builder()
+ .add("AppStyle", "DarkMode")
+ .build());
+```
+
+
+
+
+```kotlin
+Amplify.Analytics.registerGlobalProperties(
+ AnalyticsProperties.builder()
+ .add("AppStyle", "DarkMode")
+ .build())
+```
+
+
+
+
+```java
+RxAmplify.Analytics.registerGlobalProperties(
+ AnalyticsProperties.builder()
+ .add("AppStyle", "DarkMode")
+ .build());
+```
+
+
+
+
+To unregister a global property, call `Amplify.Analytics.unregisterGlobalProperties()`:
+
+
+
+
+```java
+Amplify.Analytics.unregisterGlobalProperties("AppStyle", "OtherProperty");
+```
+
+
+
+
+```kotlin
+Amplify.Analytics.unregisterGlobalProperties("AppStyle", "OtherProperty")
+```
+
+
+
+
+```java
+RxAmplify.Analytics.unregisterGlobalProperties("AppStyle", "OtherProperty");
+```
+
+
+
+
+
+
+## Record event
+
+The Amplify analytics plugin also makes it easy to record custom events within the app. The plugin handles retry logic in the event the device looses network connectivity and automatically batches requests to reduce network bandwidth.
+
+```dart
+Future recordCustomEvent() async {
+ final event = AnalyticsEvent('PasswordReset');
+
+ event.customProperties
+ ..addStringProperty('Channel', 'SMS')
+ ..addBoolProperty('Successful', true);
+
+ // You can also add the properties one by one like the following
+ event.customProperties.addIntProperty('ProcessDuration', 792);
+ event.customProperties.addDoubleProperty('doubleKey', 120.3);
+
+ await Amplify.Analytics.recordEvent(event: event);
+}
+```
+
+
+
+The AWS Pinpoint event count updates in minutes after recording your event.
+
+However, it can take upwards of 30 minutes for the event to display in the Filter section, and for its custom attributes to appear in Pinpoint.
+
+
+
+## Flush events
+
+Events have default configuration to flush out to the network every 30 seconds. If you would like to change this, update `amplifyconfiguration.dart` with the value in milliseconds you would like for `autoFlushEventsInterval`. This configuration will flush events every 10 seconds:
+
+```json
+{
+ "UserAgent": "aws-amplify-cli/2.0",
+ "Version": "1.0",
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "AppID",
+ "region": "Region"
+ },
+ "pinpointTargeting": {
+ "region": "Region"
+ },
+ "autoFlushEventsInterval": 10
+ }
+ }
+ }
+}
+```
+
+> **Note**
+>
+> Setting `autoFlushEventsInterval` to 0 will **disable** the automatic flush of events and you will be responsible for submitting them.
+
+To manually flush events, call:
+
+```dart
+await Amplify.Analytics.flushEvents();
+```
+
+## Global Properties
+
+You can register global properties which will be sent along with all invocations of `Amplify.Analytics.recordEvent`.
+
+```dart
+Future registerGlobalProperties() async {
+ final properties = CustomProperties()
+ ..addStringProperty('AppStyle', 'DarkMode');
+ await Amplify.Analytics.registerGlobalProperties(
+ globalProperties: properties,
+ );
+}
+```
+
+To unregister a global property, call `Amplify.Analytics.unregisterGlobalProperties()`:
+
+```dart
+Future unregisterGlobalProperties() async {
+ await Amplify.Analytics.unregisterGlobalProperties(
+ propertyNames: ['AppStyle', 'OtherProperty'],
+ );
+}
+```
+
+Furthermore, you can remove all global properties by calling `unregisterGlobalProperties` without `propertyNames`:
+
+```dart
+Future unregisterAllGlobalProperties() async {
+ await Amplify.Analytics.unregisterGlobalProperties();
+}
+```
+
+
+
+
+
+## Record Event
+
+The Amplify Analytics plugin provides a simple interface to record custom events within your app:
+
+```swift
+let properties: AnalyticsProperties = [
+ "eventPropertyStringKey": "eventPropertyStringValue",
+ "eventPropertyIntKey": 123,
+ "eventPropertyDoubleKey": 12.34,
+ "eventPropertyBoolKey": true
+]
+
+let event = BasicAnalyticsEvent(
+ name: "eventName",
+ properties: properties
+)
+
+Amplify.Analytics.record(event: event)
+```
+
+
+
+The AWS Pinpoint event count updates in minutes after recording your event.
+
+However, it can take upwards of 30 minutes for the event to display in the Filter section, and for its custom attributes to appear in Pinpoint.
+
+
+
+## Flush Events
+
+By default, events are automatically flushed out to the network every 60 seconds.
+
+If you would like to change this, update `amplifyconfiguration.json` and set the value you would prefer under `autoFlushEventsInterval`, expressed in seconds:
+
+```json
+{
+ "UserAgent": "aws-amplify-cli/2.0",
+ "Version": "1.0",
+ "analytics": {
+ "plugins": {
+ "awsPinpointAnalyticsPlugin": {
+ "pinpointAnalytics": {
+ "appId": "AppID",
+ "region": "Region"
+ },
+ "autoFlushEventsInterval": 60
+ }
+ }
+ }
+}
+```
+
+> **Note**
+>
+> Setting `autoFlushEventsInterval` to 0 will **disable** the automatic flush of events and you will be responsible for submitting them.
+
+To manually submit the recoded events to the backend, call:
+
+```swift
+Amplify.Analytics.flushEvents()
+```
+
+The plugin automatically batches requests in order to reduce network bandwidth and handles the retry logic if the device loses connectivity.
+
+## Authentication events
+
+Indicate how frequently users authenticate with your application.
+
+On the **Analytics** page, the **Users** tab displays charts for **Sign-ins, Sign-ups, and Authentication failures**.
+
+To learn how frequently users authenticate with your app, update your application code so that Pinpoint receives the following standard event types for authentication:
+
+ - `_userauth.sign_in`
+ - `_userauth.sign_up`
+ - `_userauth.auth_fail`
+
+You can report authentication events by doing either of the following:
+
+ - Managing user sign-up and sign-in with Amazon Cognito user pools.
+
+ Cognito user pools are user directories that make it easier to add sign-up and sign-in to your app. As users authenticate with your app, Cognito reports authentication events to Pinpoint. For more information, see [Using Amazon Pinpoint Analytics with Amazon Cognito User Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-pinpoint-integration.html) in the _Amazon Cognito Developer Guide_. Also update **amplifyconfiguration.json** by adding the `PinpointAppId` key under `CognitoUserPool`.
+
+ ```json
+ "CognitoUserPool": {
+ "Default": {
+ "PoolId": "",
+ "AppClientId": "",
+ "Region": "",
+ "PinpointAppId": ""
+ }
+ }
+ ```
+
+- Manually recording events using the `recordEvent()` API.
+
+ If you don't want to use Cognito user pools, you can use the Pinpoint client to record and submit authentication events, as shown in the following examples. In these examples, the event type is set to `_userauth.sign_in`, but you can substitute any authentication event type.
+
+```swift
+func sendUserSignInEvent() {
+ let event = BasicAnalyticsEvent(
+ name: "_userauth.sign_in"
+ )
+ Amplify.Analytics.record(event: event)
+}
+```
+
+## Global Properties
+
+You can register properties which will be included across all `Amplify.Analytics.record(event:)` calls.
+
+```swift
+let globalProperties: AnalyticsProperties = [
+ "globalPropertyKey": "value"
+]
+Amplify.Analytics.registerGlobalProperties(globalProperties)
+```
+
+To unregister global properties, call `Amplify.Analytics.unregisterGlobalProperties()`:
+
+```swift
+// When called with no arguments, it unregisters all global properties
+Amplify.Analytics.unregisterGlobalProperties()
+
+// Or you can specify which properties to unregister
+let globalProperties = ["globalPropertyKey1", "globalPropertyKey2"]
+Amplify.Analytics.unregisterGlobalProperties(globalProperties)
+```
+
+
+
+
+
+## Recording Custom Events
+
+To record custom events call the `record` API:
+
+```javascript
+import { record } from 'aws-amplify/analytics';
+
+record({
+ name: 'albumVisit',
+});
+```
+
+
+
+Analytics events are buffered in memory and periodically sent to the service and not saved locally between application sessions. If the session is ended before a buffered event is sent, it will be lost. Use the `flushEvents` API to manually send buffered events to the service.
+
+
+
+## Record a Custom Event with Attributes
+
+The `record` API lets you add additional attributes to an event. For example, to record _artist_ information with an _albumVisit_ event:
+
+```javascript
+import { record } from 'aws-amplify/analytics';
+
+record({
+ name: 'albumVisit',
+ attributes: { genre: '', artist: '' },
+});
+```
+
+Recorded events will be buffered and periodically sent to Pinpoint.
+
+## Record Engagement Metrics
+
+Metrics can also be added to an event:
+
+```javascript
+import { record } from 'aws-amplify/analytics';
+
+record({
+ name: 'albumVisit',
+ metrics: { minutesListened: 30 },
+});
+```
+
+Metric values must be a `Number` type such as a float or integer.
+
+
+
+The AWS Pinpoint event count updates in minutes after recording your event.
+
+However, it can take upwards of 30 minutes for the event to display in the Filter section, and for its custom attributes to appear in Pinpoint.
+
+
+
+## Flush events
+
+The recorded events are saved in a buffer and sent to the remote server periodically. If needed, you have the option to manually clear all the events from the buffer by using the 'flushEvents' API.
+
+```javascript
+import { flushEvents } from 'aws-amplify/analytics';
+
+flushEvents();
+```
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/sdk/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/sdk/index.mdx
new file mode 100644
index 00000000000..abdd4068382
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/sdk/index.mdx
@@ -0,0 +1,99 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Use AWS SDK',
+ description: 'For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the AWSPinpoint instance.',
+ platforms: [
+ 'swift',
+ 'android'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+
+For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the underlying Amazon Pinpoint client.
+
+
+
+**Note:** While the Amplify Library for Swift is production ready, please note that the underlying AWS SDK for Swift is currently in Developer Preview, and is not yet intended for production workloads. [Here is additional reading material](https://github.com/awslabs/aws-sdk-swift/blob/main/Sources/Core/AWSSDKForSwift/Documentation.docc/stability.md) on the stability of the SDK
+
+
+
+Add the following import:
+
+```swift
+import AWSPinpointAnalyticsPlugin
+```
+
+Then retrieve the escape hatch with this code:
+
+```swift
+do {
+ // Retrieve the reference to AWSPinpointAnalyticsPlugin
+ let plugin = try Amplify.Analytics.getPlugin(for: "awsPinpointAnalyticsPlugin")
+ guard let analyticsPlugin = plugin as? AWSPinpointAnalyticsPlugin else {
+ return
+ }
+
+ // Retrieve the reference to PinpointClientProtocol
+ let pinpointClient = analyticsPlugin.getEscapeHatch()
+
+ // Make requests using pinpointClient...
+ // ...
+} catch {
+ print("Get escape hatch failed with error - \(error)")
+}
+```
+
+
+
+For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the underlying Amazon Pinpoint client.
+
+
+
+
+
+
+
+Learn more about consuming Kotlin clients from Java using either a blocking interface or an equivalent async interface based on futures [here](https://github.com/awslabs/smithy-kotlin/blob/main/docs/design/kotlin-smithy-sdk.md#java-interop).
+
+
+
+```java
+AWSPinpointAnalyticsPlugin plugin = (AWSPinpointAnalyticsPlugin)
+ Amplify.Analytics.getPlugin("awsPinpointAnalyticsPlugin");
+PinpointClient pinpointClient = plugin.getEscapeHatch();
+```
+
+
+
+
+```kotlin
+val plugin = Amplify.Analytics.getPlugin("awsPinpointAnalyticsPlugin")
+val pinpointClient = (plugin as AWSPinpointAnalyticsPlugin).escapeHatch
+```
+
+
+
+
+```java
+AWSPinpointAnalyticsPlugin plugin = (AWSPinpointAnalyticsPlugin)
+ RxAmplify.Analytics.getPlugin("awsPinpointAnalyticsPlugin");
+PinpointClient pinpointClient = plugin.getEscapeHatch();
+```
+
+
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/index.mdx
new file mode 100644
index 00000000000..c0b888919e5
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/set-up-analytics/index.mdx
@@ -0,0 +1,525 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Set up Amplify Analytics',
+ description: 'The Analytics category enables you to collect analytics data for your app. The Analytics category comes with built-in support for Amazon Pinpoint and Amazon Kinesis (Kinesis support is currently only available in the Amplify JavaScript library). The Analytics category uses Amazon Cognito Identity pools to identify users in your App. Cognito allows you to receive data from authenticated, and unauthenticated users in your App.',
+ platforms: [
+ 'javascript',
+ 'react-native',
+ 'swift',
+ 'android',
+ 'flutter',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+Amplify enables you to collect analytics data for your app. The Analytics category uses [Amazon Cognito Identity pools](https://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html) to _identify_ users in your App. Cognito allows you to receive data from authenticated, and unauthenticated users in your App.
+
+
+## Prerequisites
+
+An application with Amplify libraries integrated and a minimum target of any of the following:
+- **iOS 13.0**, using **Xcode 14.1** or later.
+- **macOS 10.15**, using **Xcode 14.1** or later.
+- **tvOS 13.0**, using **Xcode 14.3** or later.
+- **watchOS 9.0**, using **Xcode 14.3** or later.
+- **visionOS 1.0**, using **Xcode 15 beta 2** or later. (Preview support - see below for more details.)
+
+
+
+visionOS support is currently in **preview** and can be used by targeting the [`visionos-preview`](https://github.com/aws-amplify/amplify-swift/tree/visionos-preview) branch.
+As new Xcode 15 beta versions are released, the branch will be updated with any necessary fixes on a best effort basis.
+
+For more information on how to use the `visionos-preview` branch, see [Platform Support](https://github.com/aws-amplify/amplify-swift/tree/visionos-preview#platform-support).
+
+
+
+
+
+## Prerequisites
+
+* An Android application targeting Android API level 16 (Android 4.1) or above
+
+
+
+
+
+- A Flutter application targeting Flutter SDK >=3.3.0 with Amplify libraries integrated
+
+ The following are also required, depending on which platforms you are targeting:
+
+ - An iOS configuration targeting at least iOS 13.0 and XCode version >=13.2
+ - An Android configuration targeting at least Android API level 24 (Android 7.0) or above
+ - Any browser supported by Flutter for Web (you can check the list of supported browsers [here](https://docs.flutter.dev/development/platform-integration/web/faq#which-web-browsers-are-supported-by-flutter))
+ - Any Windows OS meeting Flutter minimums
+ - macOS version 10.15 or higher
+ - Any Ubuntu Linux distribution meeting Flutter minimums
+
+
+
+## Set up Analytics backend
+
+The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create the an Analytics resource powered by [Amazon Pinpoint](https://aws.amazon.com/pinpoint/).
+
+```ts title="amplify/backend.ts"
+import { auth } from "./auth/resource";
+import { data } from "./data/resource";
+import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
+import { CfnApp } from "aws-cdk-lib/aws-pinpoint";
+import { Stack } from "aws-cdk-lib/core";
+
+const backend = defineBackend({
+ auth,
+ data,
+ // additional resources
+});
+
+const analyticsStack = backend.createStack("analytics-stack");
+
+// create a Pinpoint app
+const pinpoint = new CfnApp(analyticsStack, "Pinpoint", {
+ name: "myPinpointApp",
+});
+
+// create an IAM policy to allow interacting with Pinpoint
+const pinpointPolicy = new Policy(analyticsStack, "PinpointPolicy", {
+ policyName: "PinpointPolicy",
+ statements: [
+ new PolicyStatement({
+ actions: ["mobiletargeting:UpdateEndpoint", "mobiletargeting:PutEvents"],
+ resources: [pinpoint.attrArn + "/*"],
+ }),
+ ],
+});
+
+// apply the policy to the authenticated and unauthenticated roles
+backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(pinpointPolicy);
+backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(pinpointPolicy);
+
+// patch the custom Pinpoint resource to the expected output configuration
+backend.addOutput({
+ analytics: {
+ amazon_pinpoint: {
+ app_id: pinpoint.ref,
+ aws_region: Stack.of(pinpoint).region,
+ }
+ },
+});
+```
+
+## Install Amplify Libraries
+
+
+First, install the `aws-amplify` library:
+
+```sh showLineNumbers={false}
+npm install aws-amplify
+```
+
+
+
+1. To install Amplify Libraries in your application, open your project in Xcode and select **File > Add Packages...**.
+
+2. Enter the **Amplify Library for Swift** GitHub repo URL (`https://github.com/aws-amplify/amplify-swift`) into the search bar and click **Add Package**.
+
+
+
+ **Note:** **Up to Next Major Version** should be selected from the **Dependency Rule** dropdown.
+
+
+3. Lastly, choose **AWSPinpointAnalyticsPlugin**, **AWSCognitoAuthPlugin**, and **Amplify**. Then click **Add Package**.
+
+
+
+
+Expand **Gradle Scripts**, open **build.gradle (Module :app)**. You will already have configured Amplify by following the steps in the Project Setup walkthrough.
+
+Add Analytics by adding these libraries into the dependencies block:
+
+```groovy
+dependencies {
+ // Add these lines in `dependencies`
+ implementation 'com.amplifyframework:aws-analytics-pinpoint:ANDROID_VERSION'
+ implementation 'com.amplifyframework:aws-auth-cognito:ANDROID_VERSION'
+}
+```
+
+Click **Sync Now**.
+
+
+
+In your Flutter project directory, open **pubspec.yaml**.
+Add Analytics by adding these libraries into your dependencies block:
+
+```yaml
+environment:
+ sdk: '>=2.18.0 <4.0.0'
+
+dependencies:
+ amplify_analytics_pinpoint: ^1.0.0
+ amplify_auth_cognito: ^1.0.0
+ amplify_flutter: ^1.0.0
+```
+
+
+## Initialize Amplify Analytics
+
+Import and load the configuration file in your app. It's recommended you add the Amplify configuration step to your app's root entry point.
+
+
+```js title="src/index.js"
+import { Amplify } from 'aws-amplify';
+import { record } from 'aws-amplify/analytics';
+import amplifyconfig from './amplifyconfiguration.json';
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: amplifyconfig.Analytics,
+});
+```
+
+
+
+```js title="pages/_app.tsx"
+import { Amplify } from 'aws-amplify';
+import { record } from 'aws-amplify/analytics';
+import amplifyconfig from '@/amplifyconfiguration.json';
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: amplifyconfig.Analytics,
+});
+```
+
+
+
+To use the Amplify Analytics and Authentication categories in your app, you need to create and configure their corresponding plugins by calling the `Amplify.add(plugin:)` and `Amplify.configure()` methods.
+
+
+
+
+
+Add the following imports to the top of your main `App` file:
+
+```swift
+import Amplify
+import AWSCognitoAuthPlugin
+import AWSPinpointAnalyticsPlugin
+```
+
+Add the following code to its initializer. If there is none, you can create a default `init`:
+
+```swift
+init() {
+ do {
+ try Amplify.add(plugin: AWSCognitoAuthPlugin())
+ try Amplify.add(plugin: AWSPinpointAnalyticsPlugin())
+ try Amplify.configure()
+ print("Amplify configured with Auth and Analytics plugins")
+ } catch {
+ print("Failed to initialize Amplify with \(error)")
+ }
+}
+```
+
+
+
+
+
+Add the following imports to the top of your `AppDelegate.swift` file:
+
+```swift
+import Amplify
+import AWSCognitoAuthPlugin
+import AWSPinpointAnalyticsPlugin
+```
+
+Add the following code to the `application:didFinishLaunchingWithOptions` method:
+
+```swift
+func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+) -> Bool {
+ do {
+ try Amplify.add(plugin: AWSCognitoAuthPlugin())
+ try Amplify.add(plugin: AWSPinpointAnalyticsPlugin())
+ try Amplify.configure()
+ print("Amplify configured with Auth and Analytics plugins")
+ } catch {
+ print("Failed to initialize Amplify with \(error)")
+ }
+
+ return true
+}
+```
+
+
+
+
+
+Upon building and running this application you should see the following in your console window:
+
+```console
+Amplify configured with Auth and Analytics plugin
+```
+
+
+
+Add the Auth and Analytics plugin, along with any other plugins you may have added as described in the **Project Setup** section;
+
+```dart
+import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart';
+import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
+import 'package:amplify_flutter/amplify_flutter.dart';
+import 'package:flutter/material.dart';
+
+import 'amplifyconfiguration.dart';
+
+Future _configureAmplify() async {
+ // Add Pinpoint and Cognito Plugins, and any other plugins you want to use
+ final analyticsPlugin = AmplifyAnalyticsPinpoint();
+ final authPlugin = AmplifyAuthCognito();
+ await Amplify.addPlugins([analyticsPlugin, authPlugin]);
+}
+```
+
+
+
+When running your app on MacOS you will need to enable keychain sharing in Xcode, as described in the [Project setup guide](/gen1/[platform]/start/project-setup/platform-setup/#enable-keychain).
+
+
+
+Make sure that the amplifyconfiguration.dart file generated in the project setup is included and sent to Amplify.configure:
+
+```dart
+import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart';
+import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
+import 'package:amplify_flutter/amplify_flutter.dart';
+import 'package:flutter/material.dart';
+
+import 'amplifyconfiguration.dart';
+
+Future _configureAmplify() async {
+ // ...
+ await Amplify.addPlugins([analyticsPlugin, authPlugin]);
+
+ // Once Plugins are added, configure Amplify
+ // Note: Amplify can only be configured once.
+ try {
+ await Amplify.configure(amplifyconfig);
+ } on AmplifyAlreadyConfiguredException {
+ safePrint(
+ 'Tried to reconfigure Amplify; this can occur when your app restarts on Android.',
+ );
+ }
+}
+```
+
+Your class will look like this:
+
+```dart
+import 'package:amplify_flutter/amplify_flutter.dart';
+import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart';
+import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
+import 'package:flutter/material.dart';
+
+import 'amplifyconfiguration.dart';
+
+Future _configureAmplify() async {
+ // Add any Amplify plugins you want to use
+ final analyticsPlugin = AmplifyAnalyticsPinpoint();
+ final authPlugin = AmplifyAuthCognito();
+ await Amplify.addPlugins([analyticsPlugin, authPlugin]);
+
+ // Once Plugins are added, configure Amplify
+ // Note: Amplify can only be configured once.
+ try {
+ await Amplify.configure(amplifyconfig);
+ } on AmplifyAlreadyConfiguredException {
+ safePrint(
+ 'Tried to reconfigure Amplify; this can occur when your app restarts on Android.',
+ );
+ }
+}
+
+Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ await _configureAmplify();
+ runApp(const MyApp());
+}
+
+class MyApp extends StatefulWidget {
+ const MyApp({Key? key}): super(key: key);
+
+ // ...
+}
+```
+
+
+
+To initialize the Amplify Auth and Analytics categories you call `Amplify.addPlugin()` method for each category. To complete initialization call `Amplify.configure()`.
+
+Add the following code to your `onCreate()` method in your application class:
+
+
+
+
+```java
+import android.util.Log;
+import com.amplifyframework.AmplifyException;
+import com.amplifyframework.analytics.pinpoint.AWSPinpointAnalyticsPlugin;
+import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
+import com.amplifyframework.core.Amplify;
+```
+
+```java
+Amplify.addPlugin(new AWSCognitoAuthPlugin());
+Amplify.addPlugin(new AWSPinpointAnalyticsPlugin());
+```
+
+Your class will look like this:
+
+```java
+public class MyAmplifyApp extends Application {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ try {
+ // Add these lines to add the AWSCognitoAuthPlugin and AWSPinpointAnalyticsPlugin plugins
+ Amplify.addPlugin(new AWSCognitoAuthPlugin());
+ Amplify.addPlugin(new AWSPinpointAnalyticsPlugin());
+ Amplify.configure(getApplicationContext());
+
+ Log.i("MyAmplifyApp", "Initialized Amplify");
+ } catch (AmplifyException error) {
+ Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
+ }
+ }
+}
+```
+
+
+
+
+```kotlin
+import android.util.Log
+import com.amplifyframework.AmplifyException
+import com.amplifyframework.analytics.pinpoint.AWSPinpointAnalyticsPlugin
+import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
+import com.amplifyframework.core.Amplify
+```
+
+```kotlin
+Amplify.addPlugin(AWSCognitoAuthPlugin())
+Amplify.addPlugin(AWSPinpointAnalyticsPlugin())
+```
+
+Your class will look like this:
+
+```kotlin
+class MyAmplifyApp : Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ try {
+ // Add these lines to add the AWSCognitoAuthPlugin and AWSPinpointAnalyticsPlugin plugins
+ Amplify.addPlugin(AWSCognitoAuthPlugin())
+ Amplify.addPlugin(AWSPinpointAnalyticsPlugin())
+ Amplify.configure(applicationContext)
+
+ Log.i("MyAmplifyApp", "Initialized Amplify")
+ } catch (error: AmplifyException) {
+ Log.e("MyAmplifyApp", "Could not initialize Amplify", error)
+ }
+ }
+}
+```
+
+
+
+
+```java
+import android.util.Log;
+import com.amplifyframework.AmplifyException;
+import com.amplifyframework.analytics.pinpoint.AWSPinpointAnalyticsPlugin;
+import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
+import com.amplifyframework.rx.RxAmplify;
+```
+
+```java
+RxAmplify.addPlugin(new AWSCognitoAuthPlugin());
+RxAmplify.addPlugin(new AWSPinpointAnalyticsPlugin());
+```
+
+Your class will look like this:
+
+```java
+public class MyAmplifyApp extends Application {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ try {
+ // Add these lines to add the AWSCognitoAuthPlugin and AWSPinpointAnalyticsPlugin plugins
+ RxAmplify.addPlugin(new AWSCognitoAuthPlugin());
+ RxAmplify.addPlugin(new AWSPinpointAnalyticsPlugin());
+ RxAmplify.configure(getApplicationContext());
+
+ Log.i("MyAmplifyApp", "Initialized Amplify");
+ } catch (AmplifyException error) {
+ Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
+ }
+ }
+}
+```
+
+
+
+
+
+
+Next Steps:
+
+Congratulations! Now that you have Analytics' backend provisioned and Analytics library installed. Check out the following links to see Amplify Analytics use cases:
+
+- [Record Events](/[platform]/build-a-backend/add-aws-services/analytics/record-events/)
+- [Track Sessions](/[platform]/build-a-backend/add-aws-services/analytics/auto-track-sessions/)
+- [Identify User](/[platform]/build-a-backend/add-aws-services/analytics/identify-user/)
+
+### References
+
+[Amazon Pinpoint Construct Library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_pinpoint-readme.html)
+
+
+
+## Known Issues
+
+When importing alternative service providers listed below, instead of the default Pinpoint provider:
+
+- Kinesis (`aws-amplify/analytics/kinesis`)
+- Kinesis Data Firehose (`aws-amplify/analytics/kinesis-firehose`)
+- Personalize Event (`aws-amplify/analytics/personalize`)
+
+you may encounter the following error when starting the bundler:
+
+> Error: Unable to resolve module stream from /path/to/node_modules/@aws-sdk/... This is a [known issue](https://github.com/aws/aws-sdk-js-v3/issues/4877). Please follow [the steps](https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1656007484) outlined in the issue to resolve the error.
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/storing-data/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/storing-data/index.mdx
new file mode 100644
index 00000000000..e40b77ceee7
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/storing-data/index.mdx
@@ -0,0 +1,193 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Storing analytics data',
+ description: 'The Amazon Data Firehose analytics provider allows you to send analytics data to an Amazon Data Firehose stream for reliably storing data.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue',
+ 'react-native',
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+The Amazon Data Firehose analytics provider allows you to send analytics data to an [Amazon Data Firehose](https://aws.amazon.com/firehose/) stream for reliably storing data.
+
+## Setup Firehose stream
+
+The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create the Analytics resource powered by [Amazon Data Firehose](https://aws.amazon.com/firehose/).
+
+Let's create a storage bucket to store the data from Amazon Data Firehose stream.
+
+```ts title="amplify/storage/resource.ts"
+import { defineStorage } from "@aws-amplify/backend";
+
+// Define the S3 bucket resource
+export const storage = defineStorage({
+ name: "FirehoseDestinationBucket",
+});
+
+```
+
+next, let's create the Amazon Data Firehose resource.
+
+```ts title="amplify/backend.ts"
+import { defineBackend } from "@aws-amplify/backend";
+import { auth } from "./auth/resource";
+import { data } from "./data/resource";
+import { storage } from "./storage/resource";
+import { CfnDeliveryStream } from "aws-cdk-lib/aws-kinesisfirehose";
+import { Stack } from "aws-cdk-lib/core";
+import {
+ Policy,
+ PolicyStatement,
+ Role,
+ ServicePrincipal,
+} from "aws-cdk-lib/aws-iam";
+
+const backend = defineBackend({
+ auth,
+ data,
+ storage,
+ // additional resources
+});
+
+// Create a new stack for the Firehose resources
+const firehoseStack = backend.createStack("firehose-stack");
+
+// Access the S3 bucket resource
+const s3Bucket = backend.storage.resources.bucket;
+
+// Create a new IAM role for the Firehose
+const firehoseRole = new Role(firehoseStack, "FirehoseRole", {
+ assumedBy: new ServicePrincipal("firehose.amazonaws.com"),
+});
+
+// Grant the Firehose role read/write permissions to the S3 bucket
+s3Bucket.grantReadWrite(firehoseRole);
+
+// Create a new Firehose delivery stream
+const myFirehose = new CfnDeliveryStream(firehoseStack, "MyFirehose", {
+ deliveryStreamType: "DirectPut",
+ s3DestinationConfiguration: {
+ bucketArn: s3Bucket.bucketArn,
+ roleArn: firehoseRole.roleArn,
+ },
+ deliveryStreamName: "myFirehose",
+});
+
+// Create a new IAM policy to allow users to write to the Firehose
+const firehosePolicy = new Policy(firehoseStack, "FirehosePolicy", {
+ statements: [
+ new PolicyStatement({
+ actions: ["firehose:PutRecordBatch"],
+ resources: [myFirehose.attrArn],
+ }),
+ ],
+});
+
+// Attach the policy to the authenticated and unauthenticated IAM roles
+backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(firehosePolicy);
+backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(firehosePolicy);
+```
+
+## Installation and Configuration
+
+Ensure you have [setup IAM permissions](https://docs.aws.amazon.com/firehose/latest/dev/controlling-access.html) for `firehose:PutRecordBatch`.
+
+Example IAM policy for Amazon Data Firehose:
+
+```javascript
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": "firehose:PutRecordBatch",
+ // replace the template fields
+ "Resource": "arn:aws:firehose:::deliverystream/"
+ }]
+}
+```
+
+Configure Kinesis Firehose:
+
+```javascript
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: {
+ KinesisFirehose: {
+ // REQUIRED - Amazon Kinesis Firehose service region
+ region: 'us-east-1',
+
+ // OPTIONAL - The buffer size for events in number of items.
+ bufferSize: 1000,
+
+ // OPTIONAL - The number of events to be deleted from the buffer when flushed.
+ flushSize: 100,
+
+ // OPTIONAL - The interval in milliseconds to perform a buffer check and flush if necessary.
+ flushInterval: 5000, // 5s
+
+ // OPTIONAL - The limit for failed recording retries.
+ resendLimit: 5
+ }
+ }
+});
+```
+
+## Storing data
+
+You can send a data to a Kinesis Firehose stream with the standard `record` method. Any data is acceptable and `streamName` is required:
+
+```javascript
+import { record } from 'aws-amplify/analytics/kinesis-firehose';
+
+record({
+ data: {
+ // The data blob to put into the record
+ },
+ streamName: 'myFirehose'
+});
+```
+
+## Flush events
+The recorded events are saved in a buffer and sent to the remote server periodically *(You can tune it with the `flushInterval` option)*. If needed, you have the option to manually clear all the events from the buffer by using the 'flushEvents' API.
+
+```javascript
+import { flushEvents } from 'aws-amplify/analytics/kinesis-firehose';
+
+flushEvents();
+```
+
+
+
+## Known Issues
+
+When importing alternative service providers listed below, instead of the default Pinpoint provider:
+
+- Kinesis (`aws-amplify/analytics/kinesis`)
+- Kinesis Data Firehose (`aws-amplify/analytics/kinesis-firehose`)
+- Personalize Event (`aws-amplify/analytics/personalize`)
+
+you may encounter the following error when starting the bundler:
+
+> Error: Unable to resolve module stream from /path/to/node_modules/@aws-sdk/... This is a [known issue](https://github.com/aws/aws-sdk-js-v3/issues/4877). Please follow [the steps](https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1656007484) outlined in the issue to resolve the error.
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/analytics/streaming-data/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/streaming-data/index.mdx
new file mode 100644
index 00000000000..322ab9bfbfc
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/analytics/streaming-data/index.mdx
@@ -0,0 +1,159 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Streaming analytics data',
+ description: 'The Amazon Kinesis analytics provider allows you to send analytics data to an Amazon Kinesis stream for real-time processing.',
+ platforms: [
+ 'javascript',
+ 'react-native',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ],
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+The Amazon Kinesis analytics provider allows you to send analytics data to an [Amazon Kinesis](https://aws.amazon.com/kinesis) stream for real-time processing.
+
+## Setup Kinesis stream
+
+The following is an example utilizing the [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) to create the Analytics resource powered by [Amazon Kinesis](https://aws.amazon.com/kinesis).
+
+```ts title="amplify/backend.ts"
+import { auth } from "./auth/resource";
+import { data } from "./data/resource";
+import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
+import { Stream } from "aws-cdk-lib/aws-kinesis";
+import { Stack } from "aws-cdk-lib/core";
+
+const backend = defineBackend({
+ auth,
+ data,
+ // additional resources
+});
+
+// create a new stack for the Kinesis stream
+const kinesisStack = backend.createStack("kinesis-stack");
+
+// create a new Kinesis stream with one shard
+const kinesisStream = new Stream(kinesisStack, "KinesisStream", {
+ streamName: "myKinesisStream",
+ shardCount: 1,
+});
+
+// create a new policy to allow PutRecords to the Kinesis stream
+const kinesisPolicy = new Policy(kinesisStack, "KinesisPolicy", {
+ statements: [
+ new PolicyStatement({
+ actions: ["kinesis:PutRecords"],
+ resources: [kinesisStream.streamArn],
+ }),
+ ],
+});
+
+// apply the policy to the authenticated and unauthenticated roles
+backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy(kinesisPolicy);
+backend.auth.resources.unauthenticatedUserIamRole.attachInlinePolicy(kinesisPolicy);
+```
+
+## Installation and Configuration
+
+If you did not use the CLI, ensure you have [setup IAM permissions](https://docs.aws.amazon.com/streams/latest/dev/learning-kinesis-module-one-iam.html) for `kinesis:PutRecords`.
+
+Example IAM policy for Amazon Kinesis:
+
+```javascript
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": "kinesis:PutRecords",
+ "Resource": "arn:aws:kinesis:::stream/" // replace the template fields
+ }]
+}
+```
+
+For more information visit [Amazon Kinesis Developer Documentation](https://docs.aws.amazon.com/streams/latest/dev/learning-kinesis-module-one-iam.html).
+
+Configure Kinesis:
+
+```javascript
+// Configure the plugin after adding it to the Analytics module
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Analytics: {
+ Kinesis: {
+ // REQUIRED - Amazon Kinesis service region
+ region: 'us-east-1',
+
+ // OPTIONAL - The buffer size for events in number of items.
+ bufferSize: 1000,
+
+ // OPTIONAL - The number of events to be deleted from the buffer when flushed.
+ flushSize: 100,
+
+ // OPTIONAL - The interval in milliseconds to perform a buffer check and flush if necessary.
+ flushInterval: 5000, // 5s
+
+ // OPTIONAL - The limit for failed recording retries.
+ resendLimit: 5
+ }
+ }
+});
+```
+
+## Stream data
+
+You can send a data to a Kinesis stream with the standard `record()` method:
+
+```javascript
+import { record } from 'aws-amplify/analytics/kinesis';
+
+record({
+ data: {
+ // The data blob to put into the record
+ },
+ partitionKey: 'myPartitionKey',
+ streamName: 'myKinesisStream'
+});
+```
+
+## Flush events
+The recorded events are saved in a buffer and sent to the remote server periodically *(You can tune it with the `flushInterval` option)*. If needed, you have the option to manually clear all the events from the buffer by using the 'flushEvents' API.
+
+```javascript
+import { flushEvents } from 'aws-amplify/analytics/kinesis';
+
+flushEvents();
+```
+
+
+
+## Known Issues
+
+When importing alternative service providers listed below, instead of the default Pinpoint provider:
+
+- Kinesis (`aws-amplify/analytics/kinesis`)
+- Kinesis Data Firehose (`aws-amplify/analytics/kinesis-firehose`)
+- Personalize Event (`aws-amplify/analytics/personalize`)
+
+you may encounter the following error when starting the bundler:
+
+> Error: Unable to resolve module stream from /path/to/node_modules/@aws-sdk/... This is a [known issue](https://github.com/aws/aws-sdk-js-v3/issues/4877). Please follow [the steps](https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1656007484) outlined in the issue to resolve the error.
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-entity/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-entity/index.mdx
new file mode 100644
index 00000000000..e3e6353e3db
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-entity/index.mdx
@@ -0,0 +1,167 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Identify entities from images',
+ description: 'Learn how to identify entities from an image using Amplify.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+
+## Working with the API
+
+`Predictions.identify({entities: {...}}) => Promise<>`
+Detects entities from an image and potentially related information such as position, faces, and landmarks. Can also identify celebrities and entities that were previously added. This function returns a Promise that returns an object with the entities that was identified.
+
+Input can be sent directly from the browser (using File object or ArrayBuffer object) or an Amazon S3 key from project bucket.
+
+Detect entities directly from image uploaded from the browser. (File object)
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ entities: {
+ source: {
+ file,
+ },
+ }
+});
+console.log({ response });
+```
+
+Detect entities directly from image binary from the browser. (ArrayBuffer object)
+This technique is useful when you have base64 encoded binary image data, for example, from a webcam source.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ entities: {
+ source: {
+ bytes: imageArrayBuffer,
+ },
+ }
+});
+console.log({ response });
+```
+
+From Amazon S3 key
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ entities: {
+ source: {
+ key: pathToPhoto,
+ level: 'guest' | 'private' | 'protected', //optional, default is the configured on Storage category
+ },
+ }
+});
+console.log({ response });
+```
+
+The following options are independent of which `source` is specified. For demonstration purposes it will be used `file` but it can be used S3 Key as well.
+
+Detecting bounding box of faces from an image with its landmarks (eyes, mouth, nose).
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const { entities } = await Predictions.identify({
+ entities: {
+ source: {
+ file,
+ },
+ }
+})
+for (const { boundingBox, landmarks } of entities) {
+ const {
+ width, // ratio of overall image width
+ height, // ratio of overall image height
+ left, // left coordinate as a ratio of overall image width
+ top // top coordinate as a ratio of overall image height
+ } = boundingBox;
+
+ for(const landmark of landmarks) {
+ const {
+ type, // string "eyeLeft", "eyeRight", "mouthLeft", "mouthRight", "nose"
+ x, // ratio of overall image width
+ y // ratio of overall image height
+ } = landmark;
+ }
+}
+```
+
+Detecting celebrities on an image. It will return only celebrities the name and urls with related information.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const { entities } = await Predictions.identify({
+ entities: {
+ source: {
+ file,
+ },
+ celebrityDetection: true // boolean. It will only show detected celebrities
+ }
+})
+
+for(const { boundingBox, landmarks, metadata } of entities) {
+ const {
+ name,
+ urls
+ } = metadata; // celebrity info
+
+ // ...
+}
+.catch(err => console.log({ err }));
+```
+
+Detecting entities from previously uploaded images (e.g. Advanced Configuration for Identify Entities)
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const { entities } = await Predictions.identify({
+ entities: {
+ source: {
+ file,
+ },
+ collection: true
+ }
+})
+
+for({ boundingBox, metadata } of entities) {
+ const {
+ width, // ratio of overall image width
+ height, // ratio of overall image height
+ left, // left coordinate as a ratio of overall image width
+ top // top coordinate as a ratio of overall image height
+ } = boundingBox;
+ const { externalImageId } = metadata; // this is the object key on S3 from the original image
+}
+```
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-text/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-text/index.mdx
new file mode 100644
index 00000000000..537edddbb3e
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/identify-text/index.mdx
@@ -0,0 +1,180 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Identify text',
+ description: 'Learn how to identify text from images and documents in your application using AWS Amplify.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+## Working with the API
+
+Detect text in an input image. Input can be sent directly from the browser or an Amazon S3 key from project bucket.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ file
+ }
+ }
+});
+console.log({ response });
+```
+
+## Identify image stored in Amazon S3
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ key: pathToPhoto,
+ level?: 'guest' | 'private' | 'protected', //optional, default is configured on Storage category
+ }
+ }
+})
+console.log({ response });
+```
+
+> The following options are independent of which `source` is specified. For demonstration purposes we will reference a `file` but it can be an S3 Key as well. `Predictions.identify({text : {...}})` can detect unstructured text `PLAIN`, structured text from tables `TABLE` or text from forms `FORM`.
+
+## Identify plain text
+
+For detecting plain text, you can see the whole detected text, the lines detected, the position of each line of text, and each word.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ file
+ },
+ format: 'PLAIN'
+ }
+});
+
+const {
+ text: {
+ fullText, // String
+ lines, // Array of String ordered from top to bottom
+ linesDetailed /* Array of objects that contains
+ text, // String
+ boundingBox: {
+ width, // ratio of overall image width
+ height, // ratio of overall image height
+ left, // left coordinate as a ratio of overall image width
+ top // top coordinate as a ratio of overall image height
+ },
+ polygon // Array of { x, y } coordinates as a ratio of overall image width and height
+ */,
+ words // Array of objects that contains { text, boundingBox, polygon}
+ }
+} = response;
+```
+
+## Identify structured forms
+
+For detecting structured forms (documents, tables, etc.) from an image, `keyValues` will return a string of the entity found in the image as well as metadata such as selected checkboxes or the relative location in the image using a `boundingBox`.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ file
+ },
+ format: 'FORM'
+ }
+});
+
+const {
+ text: {
+ // same as PLAIN +
+ keyValues // Array of { key: string, value: { text: string, selected: boolean}, polygon, boundingBox }
+ }
+} = response;
+```
+
+For example the below image would return `keyValues` with "Test" or "Checked" as a key, and `true` since they are selected. The location of these elements would be returned in the `boundingBox` value.
+
+![A table of key values containing "Test" or "Checked" as keys, with a value of true indicating their selection status. The positions of these elements will be provided within the boundingBox parameter](/images/IdentifyTable.png)
+
+## Identify structured tables
+
+For detecting structured tables from an image
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ file
+ },
+ format: 'TABLE'
+ }
+});
+
+const {
+ text: {
+ // same as PLAIN +
+ tables: [
+ {
+ size: { rows, columns },
+ table // Matrix Array[ Array ] of size rows
+ // each element of the array contains { text, boundingBox, polygon, selected, rowSpan, columnSpan}
+ }
+ ]
+ }
+} = response;
+```
+
+For detecting tables and forms on the image just select format "ALL"
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+const response = await Predictions.identify({
+ text: {
+ source: {
+ file
+ },
+ format: 'ALL'
+ }
+});
+
+const {
+ text: {
+ // same as PLAIN + FORM + TABLE
+ }
+} = response;
+```
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/index.mdx
new file mode 100644
index 00000000000..ee3f4557821
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/index.mdx
@@ -0,0 +1,73 @@
+import { getChildPageNodes } from '@/utils/getChildPageNodes';
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'AI/ML Predictions',
+ description: 'Learn how to set up AI/ML Predictions',
+ route: "/[platform]/build-a-backend/add-aws-services/predictions",
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ const childPageNodes = getChildPageNodes(meta.route);
+ return {
+ props: {
+ meta,
+ childPageNodes
+ }
+ };
+}
+
+
+Amplify provides provides a solution for using AI and ML cloud services to enhance your application. Some supported use cases:
+
+
+Convert text to speech
+
+
+Transcribe audio to text
+
+
+Translate text from one language to another
+
+
+Identify text from an image
+
+
+Identify entities from an image
+
+
+Identify real world objects from an image
+
+
+Interpret text
+
+
+
+Predictions is broadly organized into 3 key use cases - Identify, Convert, and Interpret - which are available in the client API as well as CLI workflows.
+
+
+`Identify` will find text (words, tables, pages from a book), entities (faces and/or celebrities) from images. You can also identify real world landmarks or objects such as chairs, desks, etc. which are referred to as “labels” from images.
+
+
+`Convert` allows you to translate text from one source language to a target language. You can also generate speech audio from text input. Lastly, you can take an audio input and transcribe it using a websocket stream.
+
+
+`Interpret` allows you to analyze text for language, entities (places, people), key phrases, sentiment (positive, neutral, negative), and syntax (pronouns, verbs, adjectives).
+
+
+Some common use cases are listed below, as well as an advanced workflow which allows you to perform dynamic image indexing from a connected s3 bucket.
+
+Predictions comes with built-in support for [Amazon Translate](https://docs.aws.amazon.com/translate/latest/dg/what-is.html), [Amazon Polly](https://docs.aws.amazon.com/polly/latest/dg/what-is.html), [Amazon Transcribe](https://docs.aws.amazon.com/transcribe/latest/dg/what-is-transcribe.html), [Amazon Rekognition](https://docs.aws.amazon.com/rekognition/latest/dg/what-is.html), [Amazon Textract](https://docs.aws.amazon.com/textract/latest/dg/what-is.html), and [Amazon Comprehend](https://docs.aws.amazon.com/comprehend/latest/dg/what-is.html).
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/interpret-sentiment/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/interpret-sentiment/index.mdx
new file mode 100644
index 00000000000..8cddcfdcd5e
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/interpret-sentiment/index.mdx
@@ -0,0 +1,49 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Interpret sentiment',
+ description: 'Learn how to determine key phrases, sentiment, language, syntax, and entities from text using Amplify.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+## Working with the API
+
+Analyze text to find key phrases, sentiment (positive, negative, neutral), or the syntax (pronouns, verbs, etc.). You can also find entities in the text such as names or places, or perform language detection.
+
+```js
+import { Predictions } from '@aws-amplify/predictions';
+
+const result = await Predictions.interpret({
+ text: {
+ source: {
+ text: textToInterpret,
+ },
+ type: 'ALL'
+ }
+})
+console.log({ result });
+```
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/label-image/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/label-image/index.mdx
new file mode 100644
index 00000000000..27c1a61f7ba
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/label-image/index.mdx
@@ -0,0 +1,97 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Label objects in an image',
+ description: 'Learn more about how to detect labels in an image using Amplify. For example you can detect if an image has objects such as chairs, desks etc.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+## Working with the API
+
+Detect labels, such if an image has a desk or a chair in it
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.identify({
+ labels: {
+ source: {
+ file
+ },
+ type: 'LABELS'
+ }
+})
+ .then((response) => {
+ const { labels } = response;
+ labels.forEach((object) => {
+ const { name, boundingBoxes } = object;
+ });
+ })
+ .catch((err) => console.log({ err }));
+```
+
+Detect unsafe content in an image
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.identify({
+ labels: {
+ source: {
+ file
+ },
+ type: 'UNSAFE'
+ }
+})
+ .then((response) => {
+ const { unsafe } = response; // boolean
+ })
+ .catch((err) => console.log({ err }));
+```
+
+for both labels and unsafe content
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.identify({
+ labels: {
+ source: {
+ file
+ },
+ type: 'ALL'
+ }
+})
+ .then((response) => {
+ const { labels } = response;
+ const { unsafe } = response; // boolean
+ labels.forEach((object) => {
+ const { name, boundingBoxes } = object;
+ });
+ })
+ .catch((err) => console.log({ err }));
+```
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/set-up-predictions/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/set-up-predictions/index.mdx
new file mode 100644
index 00000000000..9907ea29ee7
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/set-up-predictions/index.mdx
@@ -0,0 +1,180 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Set up Predictions',
+ description: 'Get started with integrating ML capabilities into your application using Amplify',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Under active development:** The `addOutput` method for Amplify Gen 2 is under active development. The experience may change between versions of `@aws-amplify/backend`. Try it out and provide feedback at https://github.com/aws-amplify/amplify-backend/issues/new/choose
+
+
+
+
+
+### Set up the backend
+
+To enable Predictions we need to set up the appropriate IAM policy for Roles in your Cognito Identity Pool in order to use an appropriate feature. Additionally, we need to use the ```addOutput``` method to patch the custom Predictions resource to the expected output configuration.
+
+```ts title="amplify/backend.ts"
+
+import { defineBackend } from "@aws-amplify/backend";
+import { auth } from "./auth/resource";
+import { Stack } from "aws-cdk-lib";
+import { PolicyStatement } from "aws-cdk-lib/aws-iam";
+
+const backend = defineBackend({
+ auth,
+});
+
+backend.auth.resources.unauthenticatedUserIamRole.addToPrincipalPolicy(
+ new PolicyStatement({
+ actions: [
+ "translate:TranslateText",
+ "polly:SynthesizeSpeech",
+ "transcribe:StartStreamTranscriptionWebSocket",
+ "comprehend:DetectSentiment",
+ "comprehend:DetectEntities",
+ "comprehend:DetectDominantLanguage",
+ "comprehend:DetectSyntax",
+ "comprehend:DetectKeyPhrases",
+ "rekognition:DetectFaces",
+ "rekognition:RecognizeCelebrities",
+ "rekognition:DetectLabels",
+ "rekognition:DetectModerationLabels",
+ "rekognition:DetectText",
+ "rekognition:DetectLabel",
+ "textract:AnalyzeDocument",
+ "textract:DetectDocumentText",
+ "textract:GetDocumentAnalysis",
+ "textract:StartDocumentAnalysis",
+ "textract:StartDocumentTextDetection",
+ "rekognition:SearchFacesByImage",
+ ],
+ resources: ["*"],
+ })
+);
+
+backend.addOutput({
+ custom: {
+ Predictions: {
+ convert: {
+ translateText: {
+ defaults: {
+ sourceLanguage: "en",
+ targetLanguage: "es",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ speechGenerator: {
+ defaults: {
+ voiceId: "Ivy",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ transcription: {
+ defaults: {
+ language: "en-US",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ },
+ identify: {
+ identifyEntities: {
+ defaults: {
+ collectionId: "default",
+ maxEntities: 10,
+ },
+ celebrityDetectionEnabled: true,
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ identifyLabels: {
+ defaults: {
+ type: "ALL",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ identifyText: {
+ defaults: {
+ format: "ALL",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ },
+ interpret: {
+ interpretText: {
+ defaults: {
+ type: "ALL",
+ },
+ proxy: false,
+ region: Stack.of(backend.auth.resources.unauthenticatedUserIamRole)
+ .region,
+ },
+ },
+ },
+ },
+});
+
+
+
+```
+
+## Install Amplify Libraries
+
+To install the Amplify library to use predictions features, run the following commands in your project’s root folder:
+
+```sh showLineNumbers={false}
+npm install aws-amplify
+```
+
+## Configure the frontend
+
+Import and load the configuration file in your app. It's recommended you add the Amplify configuration step to your app's root entry point. For example ```index.js``` in React or ```main.ts``` in Angular.
+
+```
+
+import { Predictions } from "aws-amplify/predictions";
+import config from "./amplifyconfiguration.json";
+
+Amplify.configure(config);
+
+Amplify.configure({
+ ...Amplify.getConfig(),
+ Predictions: config.custom.Predictions,
+});
+
+```
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/text-to-speech/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/text-to-speech/index.mdx
new file mode 100644
index 00000000000..9282a4503da
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/text-to-speech/index.mdx
@@ -0,0 +1,56 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Text to speech',
+ description: 'Learn how to integrate text-to-speech capabilities into your application using Amplify.',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+### Working with the API
+
+Generate an audio buffer for playback from a text input.
+
+```
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.convert({
+ textToSpeech: {
+ source: {
+ text: textToGenerateSpeech
+ },
+ voiceId: "Amy"
+ }
+})
+.then(result => console.log({ result }))
+.catch(err => console.log({ err }));
+
+```
+
+To view the complete list of voiceId options refer to [Voices in Amazon Polly](https://docs.aws.amazon.com/polly/latest/dg/voicelist.html).
+
+
+
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/transcribe-audio/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/transcribe-audio/index.mdx
new file mode 100644
index 00000000000..3dce59aedad
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/transcribe-audio/index.mdx
@@ -0,0 +1,51 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Transcribe audio to text',
+ description: 'Learn more about how to transcribe audio to text (also known as speech-to-text) for your application using Amplify',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+## Working with the API
+
+You can transcribe a PCM Audio byte buffer to Text, such as a recording from microphone.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.convert({
+ transcription: {
+ source: {
+ bytes
+ }
+ }
+})
+.then(({ transcription: { fullText } }) => console.log({ fullText }))
+.catch((err) => console.log({ err }));
+```
+
+To view the complete list of all the supported languages and language specific features refer to [the supported languages list](https://docs.aws.amazon.com/transcribe/latest/dg/supported-languages.html). The language data input type has to support streaming for it to work with Amplify Predictions.
diff --git a/src/pages/[platform]/build-a-backend/add-aws-services/predictions/translate/index.mdx b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/translate/index.mdx
new file mode 100644
index 00000000000..706ff582d49
--- /dev/null
+++ b/src/pages/[platform]/build-a-backend/add-aws-services/predictions/translate/index.mdx
@@ -0,0 +1,56 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Translate language',
+ description: 'Learn more about how to integrate translation capabilities for your application using Amplify',
+ platforms: [
+ 'javascript',
+ 'angular',
+ 'nextjs',
+ 'react',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ meta
+ }
+ };
+}
+
+
+
+**Note:** Make sure to complete the [getting started](../set-up-predictions) section first, where you will set up the IAM roles with the right policy actions
+
+
+
+
+## Working with the API
+
+Translate text from one source language to a destination language.
+
+```javascript
+import { Predictions } from '@aws-amplify/predictions';
+
+Predictions.convert({
+ translateText: {
+ source: {
+ text: textToTranslate,
+ language : "es"
+ },
+ targetLanguage: "en"
+ }
+})
+.then(result => console.log({ result }))
+.catch(err => console.log({ err }));
+```
+
+To view the complete list of supported languages refer to [Supported languages and language codes](https://docs.aws.amazon.com/translate/latest/dg/what-is-languages.html).
+
+
diff --git a/src/pages/[platform]/build-a-backend/data/connect-from-server-runtime/nextjs-server-runtime/index.mdx b/src/pages/[platform]/build-a-backend/data/connect-from-server-runtime/nextjs-server-runtime/index.mdx
index 6c4a621c597..8b8d4adbe2b 100644
--- a/src/pages/[platform]/build-a-backend/data/connect-from-server-runtime/nextjs-server-runtime/index.mdx
+++ b/src/pages/[platform]/build-a-backend/data/connect-from-server-runtime/nextjs-server-runtime/index.mdx
@@ -29,7 +29,7 @@ export function getStaticProps(context) {
};
}
-This guide walks through how you can connect to Amplify Data from Next.js Server-side Runtimes (SSR). For Next.js applications, Amplify provides first-class support for [App Router (React Server Components, Route Handlers, and Server Actions)](https://nextjs.org/docs/app) and [Pages Router (Components, API Routes)](https://nextjs.org/docs/pages), and [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware).
+This guide walks through how you can connect to Amplify Data from Next.js Server-side Runtimes (SSR). For Next.js applications, Amplify provides first-class support for the [App Router (React Server Components, Route Handlers, and Server Actions)](https://nextjs.org/docs/app), the [Pages Router (Components, API Routes)](https://nextjs.org/docs/pages), and [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware).
Before you begin, you will need:
@@ -39,16 +39,16 @@ Before you begin, you will need:
## Connect to Amplify Data from a Next.js server runtime
-Connecting to Amplify Data will include choosing the correct Data client for Next.js server runtimes, generating the Data client, and then calling the API using generated server Data clients.
+Connecting to Amplify Data will include choosing the correct data client for Next.js server runtimes, generating the data client, and then calling the API.
### Step 1 - Choose the correct Data client for Next.js server runtimes
-Amplify offers two specialized Data clients for Next.js server runtimes (from `@aws-amplify/adapter-nextjs/data`) that you should use depending whether you retrieve the user tokens using [`cookies`](https://nextjs.org/docs/app/api-reference/functions/cookies) or [`NextRequest` and `NextResponse`](https://nextjs.org/docs/app/api-reference/functions/next-request):
+Amplify offers two specialized data clients for Next.js server runtimes (from `@aws-amplify/adapter-nextjs/data`) that you should use depending whether you retrieve the user tokens using [`cookies`](https://nextjs.org/docs/app/api-reference/functions/cookies) or [`NextRequest` and `NextResponse`](https://nextjs.org/docs/app/api-reference/functions/next-request):
-- `generateServerClientUsingCookies()` 🍪 generates a Data client with the Next.js `cookies` function from `next/headers`. Each API request dynamically refetches the cookies at runtime.
-- `generateServerClientUsingReqRes()` 🌐 generates a Data client requiring `NextRequest` and `NextResponse` provided to an `runWithAmplifyServerContext` function to prevent token contamination.
+- `generateServerClientUsingCookies()` 🍪 generates a data client with the Next.js `cookies` function from `next/headers`. Each API request dynamically refetches the cookies at runtime.
+- `generateServerClientUsingReqRes()` 🌐 generates a data client requiring `NextRequest` and `NextResponse` provided to an `runWithAmplifyServerContext` function to prevent token contamination.
-Choose the correct Data client based on your Next.js Router (App or Pages) and then the use case:
+Choose the correct data client based on your Next.js Router (App or Pages) and then the use case:
@@ -107,7 +107,7 @@ We recommend you generate Amplify Data's server client in a utility file. Then,
-To generate a Data client for the Next.js server runtime using `NextRequest` and `NextResponse`, you only need to provide your Amplify configuration. When making the individual API requests, you will need to pass it into a [`runWithAmplifyServerContext`](/[platform]/build-a-backend/server-side-rendering) function to pass in the cookies from request and response variables.
+To generate a data client for the Next.js server runtime using `NextRequest` and `NextResponse`, you only need to provide your Amplify configuration. When making the individual API requests, you will need to pass the config to the [`runWithAmplifyServerContext`](/[platform]/build-a-backend/server-side-rendering) function to pass in the cookies from request and response variables.
```ts
import { type Schema } from '@/amplify/data/resource';
@@ -136,7 +136,7 @@ We recommend you generate the server Data client in a utility file. Then, import
### Step 3 - Call API using generated server Data clients
-You can make any available query or mutation request with the generated server Data clients; however, note that subscriptions are not available within server runtimes.
+You can make any available query or mutation request with the generated server data clients; however, note that subscriptions are not available within server runtimes.
diff --git a/src/pages/[platform]/build-a-backend/functions/grant-access-to-other-resources/index.mdx b/src/pages/[platform]/build-a-backend/functions/grant-access-to-other-resources/index.mdx
index 8bb8b04b642..ff609204c3b 100644
--- a/src/pages/[platform]/build-a-backend/functions/grant-access-to-other-resources/index.mdx
+++ b/src/pages/[platform]/build-a-backend/functions/grant-access-to-other-resources/index.mdx
@@ -29,17 +29,33 @@ export function getStaticProps() {
};
}
-When you grant a function access to another resource in your Amplify backend ([such as granting access to storage](/[platform]/build-a-backend/storage/#resource-access)), that will configure environment variables for that function to make SDK calls to the AWS services it has access to. Those environment variables are typed and available as part of the `env` object.
+In order for Amplify Functions to interact with other resources they must be given access. There are two ways to grant Amplify Functions access to other resources:
-Example `defineStorage` that grants myDemoFunction access to files in `/foo/*`.
+1. [Using the `access` property](#using-the-access-property)
+2. [Using the AWS Cloud Development Kit (CDK)](#using-cdk)
+
+## Using the `access` property
+
+The `access` property is a property found in each of the `define*` functions for defining Amplify resources. It allows you specify the necessary actions using common language.
+
+
+
+When you grant a function access to another resource in your Amplify backend ([such as granting access to storage](/[platform]/build-a-backend/storage/#resource-access)), it will configure environment variables for that function to make SDK calls to the AWS services it has access to. Those environment variables are typed and available as part of the `env` object.
+
+
+
+Say you have a function that generates reports each month from your Data resource and needs to store the generated reports in Storage:
```ts title="amplify/storage/resource.ts"
-import { myDemoFunction } from '../functions/my-demo-function/resource';
+import { defineStorage } from '@aws-amplify/backend';
+import { generateMonthlyReports } from '../functions/generate-monthly-reports/resource';
export const storage = defineStorage({
- name: 'myProjectFiles',
+ name: 'myReports',
access: (allow) => ({
- '/foo/*': [allow.resource(demoFunction).to(['read', 'write', 'delete'])]
+ '/reports/*': [
+ allow.resource(generateMonthlyReports).to(['read', 'write', 'delete'])
+ ]
})
});
```
@@ -48,19 +64,76 @@ This access definition will add the environment variable `myProjectFiles_BUCKET_
Here's an example of how it can be used to upload some content to S3.
-```ts title="amplify/functions/my-demo-function/handler.ts"
-import { env } from '$amplify/env/my-demo-function';
+```ts title="amplify/functions/generate-monthly-reports/handler.ts"
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
+import { env } from '$amplify/env/generate-monthly-reports';
const s3Client = new S3Client();
-export const handler = async (event) => {
- await s3Client.send(
- new PutObjectCommand({
- Bucket: env.myProjectFiles_BUCKET_NAME,
- Key: 'foo/someFile.txt',
- Body: 'this is an example'
- })
- );
+export const handler = async () => {
+ const command = new PutObjectCommand({
+ Bucket: env.myReports_BUCKET_NAME,
+ Key: `reports/${new Date().toISOString()}.csv`,
+ Body: new Blob([''], { type: 'text/csv;charset=utf-8;' })
+ });
+
+ await s3Client.send(command);
};
```
+
+## Using CDK
+
+When permissions are needed to access resources beyond the capabilities of the `access` property, you must use CDK.
+
+Functions are created with an [_execution role_](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html), which is an IAM role that contains policies that dictate what resources your Function can interact with when it executes. This role can be extended using the [`addToRolePolicy()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.IFunction.html#addwbrtowbrrolewbrpolicystatement) method:
+
+```ts title="amplify/backend.ts"
+import { defineBackend } from "@aws-amplify/backend"
+import * as iam from "aws-cdk-lib/aws-iam"
+import * as sns from "aws-cdk-lib/aws-sns"
+import { weeklyDigest } from "./functions/weekly-digest/resource"
+
+const backend = defineBackend({
+ weeklyDigest,
+})
+
+const weeklyDigestLambda = backend.weeklyDigest.resources.lambda
+
+const topicStack = backend.createStack("WeeklyDigest")
+const topic = new sns.Topic(topicStack, "Topic", {
+ displayName: "digest",
+})
+
+// highlight-start
+const statement = new iam.PolicyStatement({
+ sid: "AllowPublishToDigest",
+ actions: ["sns:Publish"],
+ resources: [topic.topicArn],
+})
+
+weeklyDigestLambda.addToRolePolicy(statement)
+ // highlight-end
+```
+
+However some constructs provide a `grant*` method to grant access to common policy actions. Revisiting the example above you can grant the same access with `grantPublish`:
+
+```ts title="amplify/backend.ts"
+import { defineBackend } from "@aws-amplify/backend"
+import * as iam from "aws-cdk-lib/aws-iam"
+import * as sns from "aws-cdk-lib/aws-sns"
+import { weeklyDigest } from "./functions/weekly-digest/resource"
+
+const backend = defineBackend({
+ weeklyDigest,
+})
+
+const weeklyDigestLambda = backend.weeklyDigest.resources.lambda
+
+const topicStack = backend.createStack("WeeklyDigest")
+const topic = new sns.Topic(topicStack, "Topic", {
+ displayName: "digest"
+})
+
+// highlight-next-line
+topic.grantPublish(weeklyDigestLambda)
+```
diff --git a/src/pages/[platform]/build-a-backend/functions/modify-resources-with-cdk/index.mdx b/src/pages/[platform]/build-a-backend/functions/modify-resources-with-cdk/index.mdx
index 5bbf7c1bc2b..8d2dc97d6b3 100644
--- a/src/pages/[platform]/build-a-backend/functions/modify-resources-with-cdk/index.mdx
+++ b/src/pages/[platform]/build-a-backend/functions/modify-resources-with-cdk/index.mdx
@@ -29,6 +29,27 @@ export function getStaticProps(context) {
};
}
+Amplify Functions utilize the [`NodejsFunction`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) construct from the [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/). The underlying resources can be modified, overridden, or extended using CDK after setting the resource on your backend.
+
+```ts title="amplify/backend.ts"
+import { defineBackend } from '@aws-amplify/backend';
+import { myFunction } from './functions/my-function';
+
+const backend = defineBackend({
+ myFunction
+})
+
+// CDK constructs can be accessed via
+backend.myFunction.resources
+
+// where the Lambda function can be found on
+backend.myFunction.resources.lambda
+```
+
+The Lambda resource available is a representation of [`IFunction`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.IFunction.html).
+
## Adding IAM Policies
+To learn how to add IAM policies to a Function's execution role, visit the [documentation for granting access to other resources](/[platform]/build-a-backend/functions/grant-access-to-other-resources#using-cdk).
+
{/* ## Lambda Layers */}
diff --git a/src/pages/[platform]/build-ui/formbuilder/customize/index.mdx b/src/pages/[platform]/build-ui/formbuilder/customize/index.mdx
index c2e1c2e6b29..85a5afd38b1 100644
--- a/src/pages/[platform]/build-ui/formbuilder/customize/index.mdx
+++ b/src/pages/[platform]/build-ui/formbuilder/customize/index.mdx
@@ -106,6 +106,7 @@ You can manually add a form input connected to a data model to the generated for
[Select Fields](https://ui.docs.amplify.aws/react/components/selectfield), [Radio Group Fields](https://ui.docs.amplify.aws/react/components/radiogroupfield), and [Autocomplete Fields](https://ui.docs.amplify.aws/react/components/autocomplete) require a set of options for your users to choose from. For example, a "Status" input can only have the options "Not started", "In progress", and "Done". This would be identical to the above 6 steps, but in step 6 you would replace `` with ``
+{/* cSpell:disable */}
```js title="src/ui-components/TodoCreateForm.js"
// 6. Import component and add to form return
```
+{/* cSpell:enable */}
## Configure form spacings (paddings and gaps)
@@ -150,7 +152,7 @@ Add spacing to your form and between inputs. Spacing values can either be a CSS
// highlight-start
rowGap="15px" //edit horizontal gap
columnGap="15px" //edit vertical gap
- padding="20px" // edit pading around the form inputs and border
+ padding="20px" // edit padding around the form inputs and border
// highlight-end
...
```
diff --git a/src/pages/gen1/[platform]/build-a-backend/graphqlapi/connect-api-to-existing-database/index.mdx b/src/pages/gen1/[platform]/build-a-backend/graphqlapi/connect-api-to-existing-database/index.mdx
index 1abfc95f1bb..d0ca17a450a 100644
--- a/src/pages/gen1/[platform]/build-a-backend/graphqlapi/connect-api-to-existing-database/index.mdx
+++ b/src/pages/gen1/[platform]/build-a-backend/graphqlapi/connect-api-to-existing-database/index.mdx
@@ -75,13 +75,28 @@ This feature is not yet available in the Asia Pacific (Hong Kong, ap-east-1) or
+
+
First, place your database connection information (hostname, username, password, port, and database name) into Systems Manager, each as a `SecureString`.
Go to the Systems Manager console, navigate to Parameter Store, and click "Create Parameter". Create five different SecureStrings: one each for the hostname of your database server, the username and password to connect, the database port, and the database name.
Your Systems Manager configuration should look something like this:
-![Storing Database Credentials in SSM](/images/storing-db-creds-in-ssm.png)
+![A screenshot of an AWS Systems Manager console page titled "Parameter Store". The page shows a list of parameters with names like "/amplify-cdk-app/username", "/amplify-cdk-app/password", and "/amplify-cdk-app/hostname" indicating database connection details. Each parameter is of Tier "Standard" and typed as "SecureString". The last modified date is displayed for each parameter.](/images/storing-db-creds-in-ssm.png)
+
+
+First, place your database connection information (hostname, username, password, port, and database name) into Secrets Manager.
+
+Go to the Secrets Manager console, navigate to Secrets, and click "Store a new secret". You may create the secret in any manner as long as there are `username` and `password` keys defined.
+
+![A screenshot of a page in the Secrets Manager console titled "Secret value info". The screenshot shows an example of a secret's keys and values in a table including "username", "password", "engine", "host", "port", and "dbClusterIdentifier".](/images/storing-db-creds-in-secrets-manager.png)
+
+Optionally, you can decide whether to encrypt the secret using the KMS key that Secrets Manager creates or a customer managed KMS key that you create.
+
+You can also configure a rotation schedule and create a Lambda function or choose an existing Lambda function from your account to rotate the database credentials automatically.
+
+
Install the following package to add the Amplify GraphQL API construct to your dependencies:
@@ -136,6 +151,8 @@ import path from 'path';
```
In the main stack class, add the following code to define a new GraphQL API. Replace `stack` with the name of your stack instance (often referenced via `this`):
+
+
```ts
new AmplifyGraphqlApi(stack, 'SqlBoundApi', {
@@ -175,13 +192,53 @@ new AmplifyGraphqlApi(stack, 'SqlBoundApi', {
});
```
+
+
+
+```ts
+new AmplifyGraphqlApi(this, 'SqlBoundApi', {
+ apiName: 'MySqlBoundApi',
+ definition: AmplifyGraphqlDefinition.fromFilesAndStrategy(
+ [path.join(__dirname, 'schema.sql.graphql')],
+ {
+ name: 'MySQLSchemaDefinition',
+ dbType: 'MYSQL',
+ vpcConfiguration: {
+ vpcId: 'vpc-123456',
+ securityGroupIds: ['sg-123', 'sg-456'],
+ subnetAvailabilityZoneConfig: [
+ { subnetId: 'sn-123456', availabilityZone: 'us-east-1a' },
+ { subnetId: 'sn-987654', availabilityZone: 'us-east-1b' },
+ ],
+ },
+ dbConnectionConfig: {
+ databaseName: 'database',
+ port: 3306,
+ hostname: 'database-1-instance-1.id.region.rds.amazonaws.com',
+ secretArn:
+ 'arn:aws:secretsmanager:Region1:123456789012:secret:MySecret-a1b2c3',
+ },
+ }
+ ),
+ authorizationModes: {
+ defaultAuthorizationMode: 'API_KEY',
+ apiKeyConfig: {
+ expires: cdk.Duration.days(30),
+ },
+ },
+});
+```
+
+
+
+
The API will have an API key enabled for authorization.
Before deploying, make sure to:
- Set a value for `name`. This will be used to name the AppSync DataSource itself, plus any associated resources like resolver Lambdas. This name must be unique across all schema definitions in a GraphQL API.
-- Change the `dbType` to match your database engine. This is the type of the SQL database used to process model operations for this definition.Supported engines are `"MYSQL"` or `"POSTGRES"`.
+- Change the `dbType` to match your database engine. This is the type of the SQL database used to process model operations for this definition. Supported engines are `"MYSQL"` or `"POSTGRES"`.
- Update the SSM parameter paths within `dbConnectionConfig` to point to those existing in your AWS account. These are the parameters the SQL Lambda will use to connect to the database.