π¦ GravitySDK for Flutter
GravitySDK β ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ ΠΏΠ΅ΡΡΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°, ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ΠΈ ΠΏΠΎΠΊΠ°Π·Π° ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ Π² ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΡΡ
Flutter-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΡ
. SDK ΡΠ°ΠΌ Π·Π°Π³ΡΡΠΆΠ°Π΅Ρ ΠΈ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ in-app ΠΊΠΎΠ½ΡΠ΅Π½Ρ (ΠΌΠΎΠ΄Π°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ, bottom sheet, ΠΏΠΎΠ»Π½ΠΎΡΠΊΡΠ°Π½Π½ΡΠΉ ΡΠ΅ΠΆΠΈΠΌ, tooltip), Π° ΡΠ°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ inline-Π²ΠΈΠ΄ΠΆΠ΅ΡΡ ΠΈ headless-ΡΠ΅ΠΆΠΈΠΌ Π΄Π»Ρ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΊΠ°ΡΡΠΎΠΌΠ½ΠΎΠΉ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ.
π ΠΠ³Π»Π°Π²Π»Π΅Π½ΠΈΠ΅
- β¨ ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
- π Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
- βοΈ ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
- πͺ΅ ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅
- π§ ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ
- π ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΈ ΡΠΎΠ±ΡΡΠΈΡ
- π‘ ΠΡΠ»Π°ΠΉΠ½-Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ
- π ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΊΠΎΠ»Π±ΡΠΊΠΎΠ²
- π ΠΠ»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° ΠΏΠΎΠΊΠ°Π·Π° (presentation lock)
- π§© ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°
- πΌοΈ ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°
- π¨ ProductWidgetBuilder β ΠΊΠ°ΡΡΠΎΠΌΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ²
- π ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ (engagement)
- β ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ
ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
- ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ SDK Ρ ΠΊΠ»ΡΡΠΎΠΌ API ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ ΡΠ΅ΠΊΡΠΈΠΈ
- ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠΎΡΠΌΠΎΡΡΠΎΠ² ΡΠΊΡΠ°Π½ΠΎΠ² ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΡ ΡΠΎΠ±ΡΡΠΈΠΉ Ρ Π°Π²ΡΠΎΠΏΠΎΠΊΠ°Π·ΠΎΠΌ in-app ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ
- ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° ΠΏΠΎ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΡ, ID ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ»ΠΈ Π³ΡΡΠΏΠΏΠ΅
- ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π±Π°ΡΡΠΈΠ½Π³ ΠΈ Π΄Π΅Π΄ΡΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΡΡ choose-Π·Π°ΠΏΡΠΎΡΠΎΠ²
- Inline-Π²ΠΈΠ΄ΠΆΠ΅ΡΡ ΠΈ tooltip-ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ (
GravityAnchor) - Headless-ΡΠ΅ΠΆΠΈΠΌ: ΡΡΡΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ Π±Π΅Π· Π²ΡΡΡΠΎΠ΅Π½Π½ΠΎΠ³ΠΎ UI
- ΠΠ½ΠΎΠ³ΠΎΡΠ°Π³ΠΎΠ²ΡΠ΅ (multi-step) ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ
- ΠΡΠΏΡΠ°Π²ΠΊΠ° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠΉ Ρ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠΎΠΌ ΠΈ ΠΏΡΠΎΠ΄ΡΠΊΡΠ°ΠΌΠΈ
- ΠΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° Π°Π²ΡΠΎΠΏΠΎΠΊΠ°Π·Π° in-app ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° (presentation lock)
Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
ΠΠΎΠ±Π°Π²Ρ ΠΏΠ°ΠΊΠ΅Ρ Π² ΡΠ°ΠΉΠ» pubspec.yaml:
dependencies:
gravity_sdk: ^0.20.0
ΠΠ°ΡΠ΅ΠΌ Π²ΡΠΏΠΎΠ»Π½ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ:
flutter pub get
Π ΠΈΠΌΠΏΠΎΡΡΠΈΡΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ Π² ΡΠ²ΠΎΡΠΌ ΠΊΠΎΠ΄Π΅:
import 'package:gravity_sdk/gravity_sdk.dart';
Π’ΡΠ΅Π±ΡΠ΅ΡΡΡ Dart SDK ^3.10.0.
ΠΠ»Ρ iOS Π΄ΠΎΠ±Π°Π²Ρ Π² ios/Runner/Info.plist ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ App Tracking Transparency (SDK ΡΠΈΡΠ°Π΅Ρ ΡΡΠ°ΡΡΡ ΡΡΠ΅ΠΊΠΈΠ½Π³Π°):
<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>
ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
ΠΠ»Ρ ΡΠ°Π±ΠΎΡΡ SDK Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΠΈ Π±Π°Π·ΠΎΠ²ΡΡ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ, ΠΏΠ΅ΡΠ΅Π΄Π°Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ apiKey ΠΈ section. ΠΡ
ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π² Π»ΠΈΡΠ½ΠΎΠΌ ΠΊΠ°Π±ΠΈΠ½Π΅ΡΠ΅.
await GravitySDK.instance.initialize(
apiKey: 'api-key',
section: 'section',
);
ΠΠΎΠ»Π½Π°Ρ ΡΠΈΠ³Π½Π°ΡΡΡΠ°:
Future<void> initialize({
required String apiKey,
required String section,
ProductWidgetBuilder? productWidgetBuilder,
GravityEventCallback? gravityEventCallback,
GravityContentCallback? gravityContentCallback,
LogLevel logLevel = LogLevel.info,
});
productWidgetBuilderβ ΠΊΠ°ΡΡΠΎΠΌΠ½Π°Ρ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ° ΠΊΠ°ΡΡΠΎΡΠ΅ΠΊ ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ² (ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅)gravityEventCallbackβ ΠΊΠΎΠ»Π±ΡΠΊ ΡΠΎΠ±ΡΡΠΈΠΉ SDK ΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ (ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅)gravityContentCallbackβ ΠΊΠΎΠ»Π±ΡΠΊ Ρ ΡΡΡΡΠΌ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠΎΠΌ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ Π΄Π»Ρ headless-ΡΡΠ΅Π½Π°ΡΠΈΠ΅Π²logLevelβ ΡΡΠΎΠ²Π΅Π½Ρ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ
ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅
await GravitySDK.instance.initialize(
apiKey: 'api-key',
section: 'section',
logLevel: LogLevel.debug,
);
Π£ΡΠΎΠ²Π½ΠΈ: none (ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΎ), error, warn, info (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ), debug.
ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ
// Π ΡΡΠ½Π°Ρ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ
GravitySDK.instance.setUser('user-id', 'session-id');
// Π‘Π±ΡΠΎΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ ΡΠ΅ΡΡΠΈΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΈ logout)
await GravitySDK.instance.resetUser();
// ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ
GravitySDK.instance.setOptions(
options: Options(
isReturnUserInfo: true,
isImplicitImpression: true,
),
contentSettings: ContentSettings(
skusOnly: false,
fields: ['name', 'price', 'imageUrl'],
),
proxyUrl: 'https://your-proxy.com',
isFetchContentOnTrack: true,
);
// Π‘ΡΠ°ΡΡΡ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ Π½Π° push-ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ
GravitySDK.instance.setNotificationPermissionStatus(NotificationPermissionStatus.granted);
proxyUrlβ ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠΊΡΠΈisFetchContentOnTrackβ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ Π·Π°Π³ΡΡΠ·ΠΊΠ° ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° ΠΏΠΎΡΠ»Π΅trackViewNoShow()/triggerEventNoShow()(ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡtrue)NotificationPermissionStatus:granted/denied/unknown
ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΈ ΡΠΎΠ±ΡΡΠΈΡ
ΠΠ±Π° ΠΌΠ΅ΡΠΎΠ΄Π° ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ BuildContext β Π΅ΡΠ»ΠΈ ΡΠΎΠ±ΡΡΠΈΠ΅ ΡΡΠΈΠ³Π³Π΅ΡΠΈΡ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ, SDK ΡΠ°ΠΌ ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ Π΅Ρ ΠΊΠΎΠ½ΡΠ΅Π½Ρ.
await GravitySDK.instance.trackView(
context: context,
pageContext: PageContext(
type: ContextType.homepage,
data: [],
location: 'app://homepage',
),
);
await GravitySDK.instance.triggerEvent(
context: context,
events: [
AddToCartEvent(value: 99.99, productId: 'sku-123', quantity: 1, currency: 'RUB'),
],
pageContext: PageContext(
type: ContextType.product,
data: ['sku-123'],
location: 'app://product/sku-123',
),
);
ΠΠΎΡΡΡΠΏΠ½ΡΠ΅ ΡΠΎΠ±ΡΡΠΈΡ (TriggerEvent): AddToCartEvent, RemoveFromCartEvent, SyncCartEvent, PurchaseEvent, AddToWishlistEvent, SignUpEvent, LoginEvent, CustomEvent.
final purchase = PurchaseEvent(
uniqueTransactionId: 'ORDER-12345',
value: 2550.75,
currency: 'RUB',
cart: [
CartItem(productId: 'sku-123', quantity: 1, itemPrice: 100.50),
],
);
final custom = CustomEvent(
type: 'survey-completed-v1',
name: 'Survey completed',
customProps: {'surveyId': 'summer-2025', 'rating': '5'},
);
Π£ Π²ΡΠ΅Ρ ΡΠΎΠ±ΡΡΠΈΠΉ Π΅ΡΡΡ Π΄Π²Π° Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΡ ΠΏΠΎΠ»Ρ:
customPropsβ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Π°Map<String, String>(ΡΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊΠΎΠ²ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ: ΡΠΈΡΠ»Π° ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΠΉΡΠ΅ ΡΡΡΠΎΠΊΠΎΠΉ, Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΈ ΡΠΏΠΈΡΠΊΠΈ ΡΠ΅ΡΠ²Π΅Ρ Π½Π΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ);eventTimeβ ΠΊΠΎΠ³Π΄Π° ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»ΠΎ (DateTime). SDK ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ Π΅Π³ΠΎ Π² UTC; Π΅ΡΠ»ΠΈ Π½Π΅ Π·Π°Π΄Π°Π½ΠΎ, SDK ΡΠ°ΠΌ ΠΏΡΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΌΠΎΠΌΠ΅Π½Ρ Π²ΡΠ·ΠΎΠ²Π° (ΡΠΌ. Β«ΠΡΠ»Π°ΠΉΠ½-Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉΒ»), ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅ ΡΠΎΡ ΡΠ°Π½ΡΠ΅Ρ Π²Π΅ΡΠ½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ.
AddToCartEvent(
value: 99.99,
productId: 'sku-123',
quantity: 1,
customProps: {'list': 'search'},
eventTime: DateTime.now(),
);
Π£ CustomEvent Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π΅ΡΡΡ cuid / cuidType (ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, ΠΊΠ°ΠΊ Ρ LoginEvent) ΠΈ cart (ΡΠΏΠΈΡΠΎΠΊ CartItem).
ΠΡΠ»Π°ΠΉΠ½-Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ
Π‘ΠΎΠ±ΡΡΠΈΡ (triggerEvent, triggerEventNoShow, ΠΎΡΠ²Π΅ΡΡ ΡΠΎΡΠΌ) Π½Π΅ ΡΠ΅ΡΡΡΡΡΡ Π±Π΅Π· ΡΠ΅ΡΠΈ:
- ΠΠΎΡΠΎΡΠΊΠΈΠΉ ΠΏΠΎΠ²ΡΠΎΡ. ΠΡΠ±ΠΎΠΉ Π·Π°ΠΏΡΠΎΡ SDK ΠΏΡΠΈ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠ΅ ΠΈΠ»ΠΈ ΠΎΡΠ²Π΅ΡΠ΅ 408/429/5xx ΠΏΠΎΠ²ΡΠΎΡΡΠ΅ΡΡΡ Π΄ΠΎ ΡΡΡΡ
ΡΠ°Π· Ρ ΠΏΠ°ΡΠ·Π°ΠΌΠΈ 1 β 2 β 4 Ρ, ΠΏΠΎΠΊΠ° Π½Π΅ ΠΈΡΡΡΠΊ
staleContentTimeout(ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 10 Ρ). ΠΡΠΈΠ±ΠΊΠΈ Π²ΠΈΠ΄Π° 4xx Π½Π΅ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ. - ΠΡΠ΅ΡΠ΅Π΄Ρ Π½Π° Π΄ΠΈΡΠΊΠ΅. Π’Π΅Π»ΠΎ
POST /eventΠ·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ Π² SharedPreferences Π΄ΠΎ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ ΠΈ ΡΠ΄Π°Π»ΡΠ΅ΡΡΡ ΠΏΠΎΡΠ»Π΅ ΠΎΡΠ²Π΅ΡΠ° ΡΠ΅ΡΠ²Π΅ΡΠ°, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΆΠΈΠ²Π°Π΅Ρ Π΄Π°ΠΆΠ΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π·Π°Π²ΠΈΡΡΠ΅Π³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°. ΠΡΠ»ΠΈ Π·Π°ΠΏΡΠΎΡ ΡΠ°ΠΊ ΠΈ Π½Π΅ ΡΡΡΠ», ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΠΏΠΎΠ·ΠΆΠ΅ β ΠΏΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π²ΠΎΠ·Π²ΡΠ°ΡΠ΅ Π½Π° ΠΏΠ΅ΡΠ΅Π΄Π½ΠΈΠΉ ΠΏΠ»Π°Π½, ΠΏΠΎΡΠ»Π΅ Π»ΡΠ±ΠΎΠ³ΠΎ ΡΠ΄Π°ΡΠ½ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ° SDK, ΠΏΠΎ ΡΠ°ΠΉΠΌΠ΅ΡΡ Ρ Π½Π°ΡΠ°ΡΡΠ°ΡΡΠ΅ΠΉ ΠΏΠ°ΡΠ·ΠΎΠΉ (5 Ρ β¦ 15 ΠΌΠΈΠ½), ΠΏΡΠΈ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ ΡΠ΅ΡΠ΅Π·setOptionsΠΈΠ»ΠΈ ΠΏΠΎ Π²ΡΠ·ΠΎΠ²ΡflushQueue(). ΠΠ°ΡΠ·Π° ΠΏΠΎΡΠ»Π΅ ΠΎΡΠ²Π΅ΡΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° 408/429/5xx Π½Π΅ ΠΏΡΠ΅ΡΡΠ²Π°Π΅ΡΡΡ ΡΠ΄Π°ΡΠ½ΡΠΌΠΈ Π·Π°ΠΏΡΠΎΡΠ°ΠΌΠΈ ΠΊ Π΄ΡΡΠ³ΠΈΠΌ Π°Π΄ΡΠ΅ΡΠ°ΠΌ β ΡΠΎΠ»ΡΠΊΠΎ ΡΠ°ΠΉΠΌΠ΅ΡΠΎΠΌ,flushQueue()ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠΎΠΌ Π½Π° ΠΏΠ΅ΡΠ΅Π΄Π½ΠΈΠΉ ΠΏΠ»Π°Π½. ΠΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ· ΠΎΡΠ²Π΅ΡΠ° Π½Π° ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅ Π½Π΅ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°ΡΡΡΡ ΠΈ Π½Π΅ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡΡΡ. eventTime. SDK ΠΏΡΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Π²ΡΠ΅ΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ (UTC, RFC 3339) Π² ΠΌΠΎΠΌΠ΅Π½Ρ Π²ΡΠ·ΠΎΠ²Π° β Π΅ΡΡ Π΄ΠΎ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ ΡΠ΅ΡΡΠΈΠΈ, ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅ Π»ΠΎΠΆΠΈΡΡΡ Π² Π°Π½Π°Π»ΠΈΡΠΈΠΊΡ Ρ Π²Π΅ΡΠ½ΡΠΌ Π²ΡΠ΅ΠΌΠ΅Π½Π΅ΠΌ. ΠΡΠ»ΠΈ ΡΠΎΠ±ΡΡΠΈΠ΅ ΡΠΆΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡeventTime, ΠΎΠ½ΠΎ Π½Π΅ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ.- ΠΠ΄Π΅Π½ΡΠΈΡΠ½ΠΎΡΡΡ. ΠΠ°ΠΏΠΈΡΡ Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ Ρ
ΡΠ°Π½ΠΈΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ Π²ΡΠ·ΠΎΠ²Π°, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠΎΠ±ΡΡΠΈΠ΅, ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ΅ ΠΏΠΎΡΠ»Π΅
resetUser()ΠΈΠ»ΠΈ ΡΠΌΠ΅Π½Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, ΡΡ ΠΎΠ΄ΠΈΡ ΠΎΡ ΡΠΎΠ³ΠΎ, ΠΊΡΠΎ Π΅Π³ΠΎ ΡΠΎΠ²Π΅ΡΡΠΈΠ». Π‘ΠΎΠ±ΡΡΠΈΠ΅, ΠΏΠΎΡΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ΅ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ Π΄ΠΎ ΠΏΠ΅ΡΠ²ΠΎΠΉ ΡΠ΅ΡΡΠΈΠΈ (ΡΠ²Π΅ΠΆΠ°Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Π±Π΅Π· ΡΠ΅ΡΠΈ), ΠΏΡΠΈ ΠΎΡΠΏΡΠ°Π²ΠΊΠ΅ ΠΏΡΠΎΡ ΠΎΠ΄ΠΈΡ ΡΠΎΡ ΠΆΠ΅ ΠΏΡΡΡ, ΡΡΠΎ ΠΈ ΠΎΠ±ΡΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ: ΠΆΠ΄ΡΡ ΡΠΆΠ΅ ΠΈΠ΄ΡΡΡΡ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠ΅ΡΡΠΈΠΈ ΠΈΠ»ΠΈ ΡΠΎΠ·Π΄Π°ΡΡ Π΅Ρ ΡΠ°ΠΌ ΠΈ ΡΠΎΡ ΡΠ°Π½ΡΠ΅Ρuid, ΠΊΠΎΡΠΎΡΡΠΉ Π²Π΅ΡΠ½ΡΠ» ΡΠ΅ΡΠ²Π΅Ρ. ΠΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ ΡΡΠΎΡ ΠΆΠ΅uid.
Π§ΡΠΎ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ: /visit (ΠΏΡΠΎΡΠΌΠΎΡΡ ΡΠΊΡΠ°Π½Π°), /choose (Π·Π°ΠΏΡΠΎΡ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°), engagement-ΡΡΠ»Ρ (ΠΏΠΎΠΊΠ°Π·Ρ/ΠΊΠ»ΠΈΠΊΠΈ) β ΠΎΠ½ΠΈ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΊΠΎΡΠΎΡΠΊΠΈΠΌ ΠΏΠΎΠ²ΡΠΎΡΠΎΠΌ.
GravitySDK.instance.setOptions(
offlineQueue: const OfflineQueueSettings(
enabled: true, // ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΎ
maxEntries: 500, // ΡΡΠ°ΡΡΠ΅ Π·Π°ΠΏΠΈΡΠΈ Π²ΡΡΠ΅ΡΠ½ΡΡΡΡΡ
maxAge: Duration(days: 7), // ΡΡΠ°ΡΡΠ΅ β Π½Π΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ
),
staleContentTimeout: const Duration(seconds: 10),
);
// Π‘Π²ΠΎΠΉ Π΄Π΅ΡΠ΅ΠΊΡΠΎΡ ΡΠ΅ΡΠΈ? ΠΡΡΠ½ΠΈΡΠ΅ ΠΎΡΠ΅ΡΠ΅Π΄Ρ, ΠΊΠΎΠ³Π΄Π° ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΏΠΎΡΠ²ΠΈΠ»ΠΎΡΡ:
await GravitySDK.instance.flushQueue();
// ΠΡΡ
ΠΎΠ΄ ΠΈΠ· Π°ΠΊΠΊΠ°ΡΠ½ΡΠ° ΠΏΠΎ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠΈ Π΄Π°Π½Π½ΡΡ
, ΠΎΠ±ΡΠ΅Π΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ,
// ΡΠΌΠ΅Π½Π° ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ: ΡΠ΄Π°Π»ΠΈΡΡ Π²ΡΡ, ΡΡΠΎ Π΅ΡΡ Π½Π΅ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½ΠΎ. resetUser() ΠΎΡΠ΅ΡΠ΅Π΄Ρ
// Π½Π΅ ΡΡΠΎΠ³Π°Π΅Ρ β ΡΠΎΠ±ΡΡΠΈΡ, ΡΠΎΠ²Π΅ΡΡΡΠ½Π½ΡΠ΅ Π΄ΠΎ Π²ΡΡ
ΠΎΠ΄Π°, Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡΡΡ ΠΎΡ ΡΠΎΠ³ΠΎ
// ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΡ
ΡΠΎΠ²Π΅ΡΡΠΈΠ».
await GravitySDK.instance.clearQueue();
// ΠΠΈΠ°Π³Π½ΠΎΡΡΠΈΠΊΠ°:
final pending = await GravitySDK.instance.pendingDeliveries;
staleContentTimeout ΡΠ°ΠΊΠΆΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°Π΅Ρ ΠΏΠΎΠΊΠ°Π·: Π΅ΡΠ»ΠΈ ΠΎΡΠ²Π΅Ρ /visit ΠΈΠ»ΠΈ /event ΠΏΡΠΈΡΡΠ» ΠΏΠΎΠ·ΠΆΠ΅ ΡΡΠΎΠ³ΠΎ ΡΠ°ΠΉΠΌΠ°ΡΡΠ° (ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, ΡΠΊΠΎΡΠ΅Π΅ Π²ΡΠ΅Π³ΠΎ, ΡΠΆΠ΅ Π½Π° Π΄ΡΡΠ³ΠΎΠΌ ΡΠΊΡΠ°Π½Π΅), ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ Π½Π΅ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°Π΅ΡΡΡ β Π² headless-ΡΠ΅ΠΆΠΈΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄ Π²Π΅ΡΠ½ΡΡ null. ΠΡΠΎΡΠ°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° β ΡΠΆΠ΅ ΠΏΠ΅ΡΠ΅Π΄ ΡΠ°ΠΌΠΈΠΌ ΠΏΠΎΠΊΠ°Π·ΠΎΠΌ, ΠΏΠΎΡΠ»Π΅ ΠΏΠ°ΡΠ·Ρ delayTime ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ β ΡΡΠΈΡΠ°Π΅Ρ Π²ΡΡ Π²ΡΠ΅ΠΌΡ Π²ΡΠ·ΠΎΠ²Π° ΠΎΡ Π΅Π³ΠΎ Π½Π°ΡΠ°Π»Π°, Π° Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠ°ΡΠ·Ρ: Π΅ΡΠ»ΠΈ /visit ΠΎΡΠ²Π΅ΡΠΈΠ» Π±ΡΡΡΡΠΎ, Π° Π·Π°ΠΏΡΠΎΡ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° Π·Π°ΡΡΠ½ΡΠ»ΡΡ, ΠΏΠΎΠΊΠ°Π· ΡΠΎΠΆΠ΅ ΠΎΡΠΌΠ΅Π½ΡΠ΅ΡΡΡ.
ΠΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ: ΡΠΎΠ±ΡΡΠΈΠ΅, Π·Π°ΠΏΡΠΎΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π΄ΠΎΡΡΠ» Π΄ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ°, Π½ΠΎ ΠΎΡΠ²Π΅Ρ ΠΏΠΎΡΠ΅ΡΡΠ»ΡΡ, ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π΄ΠΎΡΡΠ°Π²Π»Π΅Π½ΠΎ Π΄Π²Π°ΠΆΠ΄Ρ (ΠΏΠΎΠΊΡΠΏΠΊΠΈ Π΄Π΅Π΄ΡΠΏΠ»ΠΈΡΠΈΡΡΡΡΡΡ ΠΏΠΎ uniqueTransactionId); ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠΊΠ° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π·Π°ΠΏΡΡΠ΅Π½ΠΎ; flushQueue() ΠΏΡΠΈ Π²ΡΠΊΠ»ΡΡΠ΅Π½Π½ΠΎΠΉ ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ; Π²ΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ Π½Π΅ ΠΎΡΠΌΠ΅Π½ΡΠ΅Ρ ΡΠΆΠ΅ Π½Π°ΡΠ°ΡΡΡ ΠΎΡΠΏΡΠ°Π²ΠΊΡ; pendingDeliveries ΡΡΠΈΡΡΠ²Π°Π΅Ρ ΠΈ ΡΠΎΠ±ΡΡΠΈΠ΅, Π·Π°ΠΏΡΠΎΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΈΠ΄ΡΡ ΠΏΡΡΠΌΠΎ ΡΠ΅ΠΉΡΠ°Ρ; Π² headless-ΠΌΠ΅ΡΠΎΠ΄Π°Ρ
(*NoShow) ΡΠ°ΠΉΠΌΠ°ΡΡ ΡΠ²Π΅ΠΆΠ΅ΡΡΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΡΠ²Π΅Ρ /visit//event β ΠΊΠΎΠ½ΡΠ΅Π½Ρ, ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΉ ΠΏΠΎΡΠ»Π΅ Π½Π΅Π³ΠΎ, Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΌΡ, ΠΈ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΎ ΠΏΠΎΠΊΠ°Π·Π΅ ΠΎΡΡΠ°ΡΡΡΡ Π·Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ.
ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΊΠΎΠ»Π±ΡΠΊΠΎΠ²
gravityEventCallback ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΡ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° ΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ (TrackingEvent). ΠΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²ΠΎ β ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΎΠ½Π½ΡΠ΅; ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΡΡΠ΅Π±ΡΡΡ FollowUrlEvent, FollowDeeplinkEvent ΠΈ RequestPushEvent. FollowUrlEvent.type (FollowUrlType.browser / FollowUrlType.webview) ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, Π³Π΄Π΅ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ ΠΏΡΠΎΡΠΈΡ ΠΎΡΠΊΡΡΡΡ ΡΡΡΠ»ΠΊΡ; Π΅ΡΠ»ΠΈ Π² ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΡΠΈΠΏ Π½Π΅ Π·Π°Π΄Π°Π½, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ browser:
await GravitySDK.instance.initialize(
apiKey: 'api-key',
section: 'section',
gravityEventCallback: (event) {
if (event is FollowUrlEvent) {
if (event.type == FollowUrlType.webview) {
// ΠΎΡΠΊΡΡΡΡ event.url Π²ΠΎ Π²Π½ΡΡΡΠ΅Π½Π½Π΅ΠΌ webview ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ
} else {
launchUrl(Uri.parse(event.url), mode: LaunchMode.externalApplication);
}
}
if (event is FollowDeeplinkEvent) {
// Π½Π°Π²ΠΈΠ³Π°ΡΠΈΡ ΠΏΠΎ Π΄ΠΈΠΏΠ»ΠΈΠ½ΠΊΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ
}
if (event is RequestPushEvent) {
// Π·Π°ΠΏΡΠΎΡ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ Π½Π° push-ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ
}
},
);
ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΎΠ½Π½ΡΠ΅ ΡΠΎΠ±ΡΡΠΈΡ: ContentLoadEvent, ContentImpressionEvent, ContentVisibleImpressionEvent, ContentCloseEvent, CopyEvent, CancelEvent, ProductImpressionEvent.
ΠΠ»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° ΠΏΠΎΠΊΠ°Π·Π° (presentation lock)
ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ Π·Π°ΠΏΡΠ΅ΡΠΈΡΡ Π°Π²ΡΠΎΠΏΠΎΠΊΠ°Π· in-app ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ Gravity β Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠΎΠΊΠ° ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ Π΄ΠΈΠ°Π»ΠΎΠ³, ΠΎΠ½Π±ΠΎΡΠ΄ΠΈΠ½Π³ ΠΈΠ»ΠΈ paywall:
GravitySDK.instance.lockPresentation();
// ... ΠΏΡΠΈΠΎΡΠΈΡΠ΅ΡΠ½ΡΠΉ UI ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ...
GravitySDK.instance.unlockPresentation();
ΠΠΎΠ΄ΠΏΠΈΡΠΊΠ° Π½Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ:
GravitySDK.instance.setPresentationLockListener((locked) {
debugPrint('Gravity presentation locked: $locked');
});
// ΠΎΡΠΏΠΈΡΠΊΠ°
GravitySDK.instance.setPresentationLockListener(null);
Π‘Π΅ΠΌΠ°Π½ΡΠΈΠΊΠ° (ΡΠΎΠ²ΠΏΠ°Π΄Π°Π΅Ρ Ρ iOS/Android SDK):
- ΠΏΠΎΠΊΠ° Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° Π°ΠΊΡΠΈΠ²Π½Π°,
trackViewΠΈtriggerEventΠ·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΈ ΡΠ΅Π·ΠΎΠ»Π²ΡΡ ΠΊΠΎΠ½ΡΠ΅Π½Ρ, Π½ΠΎ Π½Π΅ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ in-app UI β Π² Π»ΠΎΠ³ ΠΏΠΈΡΠ΅ΡΡΡPresentation is locked, skipped content for campaign <campaignId>; - ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΊΠΎΠ½ΡΠ΅Π½Ρ ΠΏΠΎΠ΄ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΎΠΉ Π²ΡΡ ΡΠ°Π²Π½ΠΎ Π·Π°Π³ΡΡΠΆΠ°Π΅ΡΡΡ (ΡΡ ΠΎΠ΄ΡΡ Π·Π°ΠΏΡΠΎΡ choose ΠΈ ΡΠΎΠ±ΡΡΠΈΡ contentLoaded), ΡΠ΅ΡΠ²Π΅ΡΠ½ΡΠ΅ Π»ΠΈΠΌΠΈΡΡ ΠΏΠΎΠΊΠ°Π·ΠΎΠ² ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ (frequency cap, one-shot) ΡΠ°ΡΡ ΠΎΠ΄ΡΡΡΡΡ Π΄Π°ΠΆΠ΅ Π±Π΅Π· ΠΏΠΎΠΊΠ°Π·Π°;
- Π±Π»ΠΎΠΊΠΈΡΡΠ΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π°Π²ΡΠΎΠΏΠΎΠΊΠ°Π·:
fetchAnchorContent(Π² ΡΠΎΠΌ ΡΠΈΡΠ»Π΅ Π°Π²ΡΠΎΠ·Π°Π³ΡΡΠ·ΠΊΠ° ΡΠ΅ΡΠ΅Π·GravityAnchor), step-Π½Π°Π²ΠΈΠ³Π°ΡΠΈΡ ΡΠΆΠ΅ ΠΎΡΠΊΡΡΡΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°,trackViewNoShow/triggerEventNoShowΠΈgetContentBy*ΠΏΠΎΠ΄ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΡ Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡΡ; - ΡΠΆΠ΅ ΠΎΡΠΊΡΡΡΡΠΉ in-app ΠΊΠΎΠ½ΡΠ΅Π½Ρ ΠΏΡΠΈ
lockPresentation()Π½Π΅ Π·Π°ΠΊΡΡΠ²Π°Π΅ΡΡΡ; - ΠΏΠΎΡΠ»Π΅
unlockPresentation()ΠΏΠΎΠΊΠ°Π·Ρ ΡΠ½ΠΎΠ²Π° ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Ρ Π΄Π»Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΡtrackView/triggerEvent; ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ, ΠΏΡΠΎΠΏΡΡΠ΅Π½Π½Π°Ρ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ, ΡΠ΅ΡΡΠΎΠ°ΠΊΡΠΈΠ²Π½ΠΎ Π½Π΅ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ; - ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΠ΅ Π²ΡΠ·ΠΎΠ²Ρ lock/unlock Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½Ρ; listener Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π²ΡΠ·ΠΎΠ²Π΅;
- ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ ΠΆΠΈΠ²ΡΡ Π² ΠΏΠ°ΠΌΡΡΠΈ ΠΈ ΡΠ±ΡΠ°ΡΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΡΡΠΊΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ β Π΅ΡΠ»ΠΈ ΠΎΠ½ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅ΠΆΠΈΠ²Π°ΡΡ ΡΠ΅ΡΡΠ°ΡΡ, ΡΠΎΡ
ΡΠ°Π½ΡΠΉΡΠ΅ ΠΈ Π²ΠΎΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΠΉΡΠ΅ Π΅Π³ΠΎ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ (ΠΏΡΠΈΠΌΠ΅Ρ β
PresentationLockPrefsΠ²example/); - ΡΠ΅ΠΊΡΡΠ΅Π΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π΄ΠΎΡΡΡΠΏΠ½ΠΎ ΡΠ΅ΡΠ΅Π·
GravitySDK.instance.isPresentationLocked.
ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°
ΠΠΎΠ½ΡΠ΅Π½Ρ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡΠΎΡΠΈΡΡ Π½Π°ΠΏΡΡΠΌΡΡ, Π±Π΅Π· Π°Π²ΡΠΎΠΏΠΎΠΊΠ°Π·Π°:
final bySelector = await GravitySDK.instance.getContentBySelector(
selector: 'homepage-recommendations',
pageContext: pageContext,
rules: rules, // ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎ, List<RtRule>
);
final byCampaign = await GravitySDK.instance.getContentByCampaignId(
campaignId: 'campaign-id',
pageContext: pageContext,
);
final byGroup = await GravitySDK.instance.getContentByGroup(
group: 'homepage-group',
pageContext: pageContext,
);
ΠΡΠ²Π΅Ρ β ContentResponse Ρ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡΠΌΠΈ (data), ΠΈΡ
Π²Π°ΡΠΈΠ°ΡΠΈΡΠΌΠΈ (payload) ΠΈ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠΎΠΌ (contents):
final campaign = bySelector.data.firstOrNull;
final variation = campaign?.payload.firstOrNull;
final content = variation?.contents.firstOrNull;
ΠΠ°ΡΡΠΈΠ½Π³ ΠΈ Π΄Π΅Π΄ΡΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ
ΠΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΡΠ΅ Π²ΡΠ·ΠΎΠ²Ρ getContentBySelector / getContentByCampaignId Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΡΡΡΡ Π² ΠΏΡΠ΅Π΄Π΅Π»Π°Ρ
ΠΊΠΎΡΠΎΡΠΊΠΎΠ³ΠΎ ΠΎΠΊΠ½Π° (10 ΠΌΡ):
- ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½ΡΠ΅ Π·Π°ΠΏΡΠΎΡΡ Π΄Π΅Π΄ΡΠΏΠ»ΠΈΡΠΈΡΡΡΡΡΡ β ΡΡ ΠΎΠ΄ΠΈΡ ΠΎΠ΄ΠΈΠ½ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ Π²ΡΠ·ΠΎΠ², Π²ΡΠ·ΡΠ²Π°ΡΡΠΈΠ΅ Π΄Π΅Π»ΡΡ ΠΎΠ΄ΠΈΠ½ ΠΎΡΠ²Π΅Ρ;
- ΡΠ°Π·Π½ΡΠ΅ Π·Π°ΠΏΡΠΎΡΡ Ρ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠΌ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅ΠΌ (ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ,
PageContext,Options) ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΡΡΡΡ Π² ΠΎΠ΄ΠΈΠ½ POST /choose Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌΠΈ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΠΌΠΈdata[].
ΠΡΠΎ ΠΏΡΠΎΠ·ΡΠ°ΡΠ½ΠΎ Π΄Π»Ρ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅Π³ΠΎ ΠΊΠΎΠ΄Π° ΠΈ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅Ρ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ. getContentByGroup Π² Π±Π°ΡΡΠΈΠ½Π³Π΅ Π½Π΅ ΡΡΠ°ΡΡΠ²ΡΠ΅Ρ.
ΠΡΠΈΠΌΠ΅Ρ: ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΡ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΉ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌΠΈ
final rules = [
RtRule(
type: 'filter',
conditions: [
RtRuleCondition(
field: 'category',
arguments: [RtRuleArgument(action: 'in', value: ['shoes'])],
),
],
),
];
Headless-ΡΠ΅ΠΆΠΈΠΌ
ΠΠ»Ρ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΊΠ°ΡΡΠΎΠΌΠ½ΠΎΠΉ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ Π΅ΡΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ Ρ ΡΡΡΡΠΌ JSON ΠΈ Β«Π±Π΅Π·Π·Π²ΡΡΠ½ΡΠ΅Β» Π°Π½Π°Π»ΠΎΠ³ΠΈ ΡΡΠ΅ΠΊΠΈΠ½Π³Π° (ΠΊΠΎΠ½ΡΠ΅Π½Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ, Π½ΠΎ Π½Π΅ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ):
// ΠΌΠΎΠ΄Π΅Π»Ρ + ΡΡΡΠΎΠΉ JSON
final GravityDataResponse<ContentResponse> details =
await GravitySDK.instance.getContentBySelectorWithDetails(
selector: 'homepage-banner',
pageContext: pageContext,
);
// ΡΡΠ΅ΠΊΠΈΠ½Π³ Π±Π΅Π· ΠΏΠΎΠΊΠ°Π·Π°: null, Π΅ΡΠ»ΠΈ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ Π½Π΅ ΡΡΠ°Π±ΠΎΡΠ°Π»Π°, ΠΎΡΠ²Π΅Ρ ΠΏΡΠΈΡΡΠ» ΠΏΠΎΠ·ΠΆΠ΅ staleContentTimeout ΠΈΠ»ΠΈ ΡΠΎΠ±ΡΡΠΈΠ΅ ΡΡΠ»ΠΎ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ
final GravityDataResponse<ContentResponse>? triggered =
await GravitySDK.instance.trackViewNoShow(pageContext: pageContext);
final GravityDataResponse<ContentResponse>? byEvent =
await GravitySDK.instance.triggerEventNoShow(
events: [event],
pageContext: pageContext,
);
trackViewNoShow / triggerEventNoShow Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π²ΡΠ·ΡΠ²Π°ΡΡ gravityContentCallback ΠΈ ΠΏΠΎΠ΄ΡΠΈΠ½ΡΡΡΡΡ ΡΠ»Π°Π³Ρ isFetchContentOnTrack.
ΠΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠ΅ ΠΊΠ»ΡΡΠΈ variables
ΠΡΠΎΠΌΠ΅ ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΠΏΠΎΠ»Π΅ΠΉ (title, elements, frameUI, β¦) ΠΎΠ±ΡΠ΅ΠΊΡ variables ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ Π»ΡΠ±ΡΠ΅ ΠΊΠ»ΡΡΠΈ, Π·Π°Π΄Π°Π½Π½ΡΠ΅ Π² Π΄Π°ΡΠ±ΠΎΡΠ΄Π΅ Gravity. ΠΠ½ΠΈ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π±Π΅Π· ΡΠ°Π·Π±ΠΎΡΠ° ΡΡΡΠΎΠ³ΠΎ JSON:
content.rawVariablesβ Π²Π΅ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡvariablesΠΊΠ°ΠΊMap<String, dynamic>;content.variables['<ΠΊΠ»ΡΡ>']β Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΠΎ ΠΊΠ»ΡΡΡ (Object?;nullΠΈ Π΅ΡΠ»ΠΈ ΠΊΠ»ΡΡΠ° Π½Π΅Ρ, ΠΈ Π΅ΡΠ»ΠΈ Π² Π½ΡΠΌ Π·Π°ΠΏΠΈΡΠ°Π½nullβ ΡΠ°Π·Π»ΠΈΡΠΈΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΅ΡΠ΅Π·content.rawVariables.containsKey('<ΠΊΠ»ΡΡ>'));content.variables.valueOf<T>('<ΠΊΠ»ΡΡ>')β ΡΠΎ ΠΆΠ΅, Π½ΠΎ Π²Π΅ΡΠ½ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, ΡΠΎΠ»ΡΠΊΠΎ Π΅ΡΠ»ΠΈ ΠΎΠ½ΠΎ ΠΈΠΌΠ΅Π΅Ρ ΡΠΈΠΏT, ΠΈΠ½Π°ΡΠ΅null. ΠΠ½Π°ΡΠ΅Π½ΠΈΡ ΠΏΡΠΈΡ ΠΎΠ΄ΡΡ ΠΈΠ·jsonDecode, ΠΏΠΎΡΡΠΎΠΌΡTΠ΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ JSON-ΡΠΈΠΏΠΎΠΌ: ΠΎΠ±ΡΠ΅ΠΊΡΡ βMap<String, dynamic>, ΠΌΠ°ΡΡΠΈΠ²Ρ βList<dynamic>(Π½Π΅List<String>), ΡΠΈΡΠ»Π° βnum(ΡΠ΅Π»ΠΎΠ΅15Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡdouble, Π°1.5βint), ΡΡΡΠΎΠΊΠΈ βString, ΡΠ»Π°Π³ΠΈ βbool.
rawVariables Π΅ΡΡΡ Ρ Π»ΡΠ±ΠΎΠ³ΠΎ CampaignContent, ΠΎΡΠΊΡΠ΄Π° Π±Ρ ΠΎΠ½ Π½ΠΈ ΠΏΡΠΈΡΡΠ»: getContentBySelector, β¦WithDetails, gravityContentCallback, ContentLoadEvent.content, inline-Π²ΠΈΠ΄ΠΆΠ΅ΡΡ.
final content = details.data.data.first.payload.first.contents.first;
// A/B-Π²Π°ΡΠΈΠ°ΡΠΈΡ, ΠΎΠΏΠΈΡΠ°Π½Π½Π°Ρ Π² ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ
final variant = content.variables.valueOf<Map<String, dynamic>>('inline_banner');
final label = variant?['variant'] as String?;
// Π²Π΅ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ ΡΠ΅Π»ΠΈΠΊΠΎΠΌ
final all = content.rawVariables;
ΠΠ°ΠΆΠ½ΠΎ:
rawVariablesβ ΠΏΠΎΠ»Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡvariables, Π²ΠΊΠ»ΡΡΠ°Ρ ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΊΠ»ΡΡΠΈ; ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΏΠΎΠ»Ρ (content.variables.title,content.variables.elements, β¦) ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΊΠ°ΠΊ ΡΠ°Π½ΡΡΠ΅;- ΠΊΠ°ΡΡΠ° Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠ°Ρ Π½Π° Π²Π΅ΡΡ
Π½Π΅ΠΌ ΡΡΠΎΠ²Π½Π΅ (ΠΏΠΎΠΏΡΡΠΊΠ° Π·Π°ΠΏΠΈΡΠΈ Π±ΡΠΎΡΠΈΡ
UnsupportedError), Π½ΠΎ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΈ ΡΠΏΠΈΡΠΊΠΈ β ΡΠ΅ ΠΆΠ΅ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ, ΡΡΠΎ ΠΈ Π²GravityDataResponse.json: Π½Π΅ ΠΌΡΡΠΈΡΡΠΉΡΠ΅ ΠΈΡ ; - Π½Π°Π±ΠΎΡ ΠΈ ΡΡΡΡΠΊΡΡΡΠ° ΠΊΠ»ΡΡΠ΅ΠΉ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΠΌΠΈ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ Gravity β SDK ΠΈΡ Π½Π΅ Π²Π°Π»ΠΈΠ΄ΠΈΡΡΠ΅Ρ ΠΈ Π½ΠΈΡΠ΅Π³ΠΎ ΠΎ Π½ΠΈΡ Π½Π΅ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ.
ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°
In-app ΠΊΠΎΠ½ΡΠ΅Π½Ρ (ΠΌΠΎΠ΄Π°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ, bottom sheet, ΠΏΠΎΠ»Π½ΠΎΡΠΊΡΠ°Π½Π½ΡΠΉ ΡΠ΅ΠΆΠΈΠΌ, tooltip) SDK ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΈΠ· trackView / triggerEvent β ΡΠΎΡΠΌΠ°Ρ Π·Π°Π΄Π°ΡΡΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΠΌΠΈ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ Gravity. ΠΠ½ΠΎΠ³ΠΎΡΠ°Π³ΠΎΠ²ΡΠ΅ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ (ΠΏΠ΅ΡΠ΅Ρ
ΠΎΠ΄Ρ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ°Π³Π°ΠΌΠΈ ΠΏΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ°ΠΌ) ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΌ ΡΠ΅Π½Π΄Π΅ΡΠ΅ΡΠΎΠΌ.
In-app ΡΠΎΡΠΌΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΎΠΏΡΠΎΡ Ρ ΠΎΡΠ΅Π½ΠΊΠΎΠΉ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ) ΡΠΎΠΆΠ΅ ΡΠ΅Π½Π΄Π΅ΡΡΡΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ: Π²ΡΠ±ΠΎΡ ΠΎΡΠ΅Π½ΠΊΠΈ, ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΉ Π²Π²ΠΎΠ΄ Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡΠΌΠΈ Π΄Π»ΠΈΠ½Ρ, ΡΡΠ»ΠΎΠ²Π½Π°Ρ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΠΎΡΠ²Π΅ΡΠΎΠ². ΠΠ½ΠΎΠΏΠΊΠ° ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ Π½Π΅Π°ΠΊΡΠΈΠ²Π½Π°, ΠΏΠΎΠΊΠ° ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΏΠΎΠ»Ρ Π½Π΅ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Ρ; ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π² Gravity Π±Π΅Π· ΡΡΠ°ΡΡΠΈΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. ΠΡΠ΄Π΅Π»ΡΠ½ΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ β ΠΊΡΠΎΠΌΠ΅ FollowUrlEvent, Π΅ΡΠ»ΠΈ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΡ ΠΏΠΎΡΠ»Π΅ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ Π²Π΅Π΄ΡΡ Π½Π° Π²Π½Π΅ΡΠ½ΡΡ ΡΡΡΠ»ΠΊΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π² ΠΌΠ°Π³Π°Π·ΠΈΠ½ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ).
Inline-Π²ΠΈΠ΄ΠΆΠ΅ΡΡ
ΠΡΡΡΠ°ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ Π² Π²ΡΡΡΡΠΊΡ ΡΠΊΡΠ°Π½Π°:
GravityInlineWidget(
selector: 'homepage-recommendations',
height: 250,
pageContext: pageContext,
);
GravityInlineListWidget(
group: 'homepage-group',
height: 250,
pageContext: pageContext,
);
GravityInlineWidget Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ placeholderId, width, showLoading, loadingWidget, backgroundColor, onLoaded, rules; GravityInlineListWidget β showLoading, loadingWidget, showIndicator, indicatorActiveColor, indicatorInactiveColor.
Tooltip-ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ: GravityAnchor
GravityAnchor ΠΏΠΎΠΌΠ΅ΡΠ°Π΅Ρ Π²ΠΈΠ΄ΠΆΠ΅Ρ ΠΊΠ°ΠΊ ΡΠΊΠΎΡΡ Π΄Π»Ρ tooltip-ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈ ΡΠ°ΠΌ Π·Π°Π³ΡΡΠΆΠ°Π΅Ρ Π΅Ρ ΠΊΠΎΠ½ΡΠ΅Π½Ρ:
GravityAnchor(
selector: 'profile_tooltip',
pageContext: pageContext,
builder: (context, onReady) {
return GravityInlineWidget(
selector: 'profile_inline',
height: 120,
pageContext: pageContext,
onLoaded: onReady,
);
},
);
ΠΠ°Π³ΡΡΠ·ΠΈΡΡ ΡΠΊΠΎΡΠ½ΡΠΉ ΠΊΠΎΠ½ΡΠ΅Π½Ρ ΠΌΠΎΠΆΠ½ΠΎ ΠΈ Π²ΡΡΡΠ½ΡΡ:
await GravitySDK.instance.fetchAnchorContent(
context: context,
selector: 'profile_tooltip',
pageContext: pageContext, // ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎ
);
ProductWidgetBuilder β ΠΊΠ°ΡΡΠΎΠΌΠΈΠ·Π°ΡΠΈΡ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ²
ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ ΠΏΡΠΎΠ΄ΡΠΊΡΡ (ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΈ, Π°ΠΊΡΠΈΠΈ). Π§ΡΠΎΠ±Ρ ΠΊΠ°ΡΡΠΎΡΠΊΠΈ ΡΠΎΠ²Π°ΡΠΎΠ² Π²ΠΏΠΈΡΡΠ²Π°Π»ΠΈΡΡ Π² ΡΡΠΈΠ»Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, ΠΏΠ΅ΡΠ΅Π΄Π°ΠΉΡΠ΅ ΡΠ²ΠΎΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ProductWidgetBuilder ΠΏΡΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ; ΠΈΠ½Π°ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ DefaultProductWidgetBuilder.
class MyProductWidgetBuilder extends ProductWidgetBuilder {
@override
Widget build({
required BuildContext context,
required Slot product,
required CampaignContent content,
required Campaign campaign,
}) {
final item = product.item; // Map<String, dynamic> β Π°ΡΡΠΈΠ±ΡΡΡ ΡΠΎΠ²Π°ΡΠ° ΠΈΠ· ΡΠΈΠ΄Π°
final imageUrl = item['imageUrl'] as String?;
return GestureDetector(
onTap: () {
GravitySDK.instance.sendProductEngagement(
ProductClickEngagement(product, content, campaign),
);
},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (imageUrl != null) Image.network(imageUrl, height: 160, fit: BoxFit.cover),
Text(item['name'] as String? ?? '', style: const TextStyle(fontWeight: FontWeight.bold)),
Text('${item['price'] ?? ''}'),
],
),
),
);
}
}
await GravitySDK.instance.initialize(
apiKey: 'api-key',
section: 'section',
productWidgetBuilder: MyProductWidgetBuilder(),
);
ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ (engagement)
ΠΡΠΈ ΠΊΠ°ΡΡΠΎΠΌΠ½ΠΎΠΉ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ΅ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ° ΠΎΡΠΏΡΠ°Π²Π»ΡΠΉΡΠ΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Π²ΡΡΡΠ½ΡΡ:
// ΠΊΠΎΠ½ΡΠ΅Π½Ρ
GravitySDK.instance.sendContentEngagement(ContentImpressionEngagement(content, campaign));
GravitySDK.instance.sendContentEngagement(ContentVisibleImpressionEngagement(content, campaign));
GravitySDK.instance.sendContentEngagement(ContentCloseEngagement(content, campaign));
GravitySDK.instance.sendContentEngagement(ContentClickEngagement(content, campaign));
// ΠΏΡΠΎΠ΄ΡΠΊΡΡ
GravitySDK.instance.sendProductEngagement(ProductClickEngagement(slot, content, campaign));
GravitySDK.instance.sendProductEngagement(ProductVisibleImpressionEngagement(slot, content, campaign));
ContentClickEngagement β ΠΊΠ»ΠΈΠΊ ΠΏΠΎ ΠΊΠΎΠ½ΡΠ΅Π½ΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡΡΠΈΡΠΎΠ²Π°Π»ΠΎ ΡΠ°ΠΌΠΎ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, A/B-Π²Π°ΡΠΈΠ°ΡΠΈΡ Π² headless-ΡΠ΅ΠΆΠΈΠΌΠ΅). SDK Π±Π΅ΡΡΡ URL ΠΈΠ· content.events Ρ ΡΠΈΠΏΠΎΠΌ click; Π΅ΡΠ»ΠΈ ΡΠ΅ΡΠ²Π΅Ρ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ Π½Π΅ ΠΏΡΠΈΡΠ»Π°Π», Π²ΡΠ·ΠΎΠ² Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ. ΠΠ»Ρ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΈΡΡΠ΅Ρ ΡΠ°ΠΌ SDK, ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π΅Π³ΠΎ Π½Π΅ Π½ΡΠΆΠ½ΠΎ: ΠΊΠ½ΠΎΠΏΠΊΠΈ follow_url, follow_deeplink ΠΈ request_push ΡΠΆΠ΅ ΡΠΈΠΊΡΠΈΡΡΡΡ ΠΊΠ»ΠΈΠΊ ΡΠ²ΠΎΠΈΠΌΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠΌΠΈ, ΠΈ ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² ΡΠ΄Π²ΠΎΠΈΡ Π΅Π³ΠΎ Π² ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠ΅.
ContentEngagement β sealed-ΠΊΠ»Π°ΡΡ: Π΅ΡΠ»ΠΈ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π΅ΡΡΡ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠΈΠΉ switch ΠΏΠΎ Π΅Π³ΠΎ ΠΏΠΎΠ΄ΡΠΈΠΏΠ°ΠΌ, ΠΏΠΎΡΠ»Π΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ Π²Π΅ΡΠΊΡ Π΄Π»Ρ ContentClickEngagement.
ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ
ΠΠ΅ΡΠ΅Π΄ Π²ΡΠ·ΠΎΠ²Π°ΠΌΠΈ SDK Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎ ΠΎΠ½ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½. Π ΠΏΡΠΎΡΠΈΠ²Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠ±ΡΠΎΡΠ΅Π½ΠΎ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:
GravitySDK is not initialized. Call initialize() first.
Π‘Π΅ΡΠ΅Π²ΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ getContentBy* ΠΏΡΠΎΠ±ΡΠ°ΡΡΠ²Π°ΡΡΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΌΡ ΠΊΠΎΠ΄Ρ (DioException); trackView / triggerEvent ΠΈ inline-Π²ΠΈΠ΄ΠΆΠ΅ΡΡ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΡΠ²ΠΎΠΈ ΠΎΡΠΈΠ±ΠΊΠΈ ΡΠ°ΠΌΠΎΡΡΠΎΡΡΠ΅Π»ΡΠ½ΠΎ ΠΈ Π½Π΅ ΡΠΎΠ½ΡΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅. Π‘Π΅ΡΠ΅Π²ΡΠ΅ ΡΠ±ΠΎΠΈ ΠΏΡΠΈ ΠΎΡΠΏΡΠ°Π²ΠΊΠ΅ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΏΠΎΠΊΡΡΡΡ ΠΏΠΎΠ²ΡΠΎΡΠΎΠΌ ΠΈ ΠΎΡΠ΅ΡΠ΅Π΄ΡΡ Π½Π° Π΄ΠΈΡΠΊΠ΅ β ΡΠΌ. ΠΡΠ»Π°ΠΉΠ½-Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ.