AttentionVerify by OMNIYA is a WordPress plugin that uses camera-based attention verification to reward customers for genuinely watching a video on your WooCommerce product pages. When a customer reaches the required attention score, the plugin creates a single-use WooCommerce coupon for them.
Please read this section before using the plugin on a live store. The widget uses the visitor’s camera, so you should mention it in your privacy policy and, depending on where your visitors are, obtain their consent before the widget starts. This is general information, not legal advice.
In the visitor’s browser
In your Firebase project (the project whose credentials you enter in Settings)
In your WordPress database
This plugin writes session documents directly to your own Firebase project from the browser (there is no server-side Firebase Admin SDK involved). Apply the following rules in your Firebase Console under Firestore Database Rules. They constrain writes to the exact shape this plugin uses, and prevent a session document from being rewritten once it reaches a terminal state:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /sessions/{sessionId} {
allow get: if true; // required so the plugin's server-side verification (a public, unauthenticated read) can confirm completion status before issuing a reward
allow list: if false;
// hasOnly (not just hasAll) is what actually prevents a client from
// attaching an extra field — an "image", "face_data", "video", or
// anything else — alongside the required ones. hasAll alone only
// checks that the required keys are present; it does not stop
// additional keys from being included in the same write.
allow create: if request.resource.data.keys().hasAll(['session_id','ad_id','completion_status','created_at'])
&& request.resource.data.keys().hasOnly(['session_id','ad_id','completion_status','attention_duration','face_lost_count','head_moved_count','tab_switch_count','fail_count','created_at','updated_at'])
&& request.resource.data.completion_status == 'in_progress'
&& request.resource.data.session_id is string
&& request.resource.data.session_id.size() < 200;
allow update: if resource.data.completion_status == 'in_progress'
&& request.resource.data.keys().hasOnly(['session_id','ad_id','completion_status','attention_duration','face_lost_count','head_moved_count','tab_switch_count','fail_count','created_at','updated_at'])
&& request.resource.data.session_id == resource.data.session_id
&& request.resource.data.ad_id == resource.data.ad_id
&& request.resource.data.completion_status in ['in_progress', 'verified', 'failed'];
allow delete: if false;
match /events/{eventId} {
allow create: if request.resource.data.keys().hasAll(['type','message','timestamp'])
&& request.resource.data.keys().hasOnly(['type','message','timestamp']);
allow read, update, delete: if false;
}
}
match /publisher_stats/totals {
allow get: if true;
allow list: if false;
allow write: if request.resource.data.keys().hasOnly(['total_seconds_watched','completed_attention','uncompleted_attention','updated_at']);
allow delete: if false;
}
match /{document=**} {
allow read, write: if false;
}
}
}
Important limitation, stated plainly: these rules constrain the shape of what can be written (field names, types, and that a completed session can’t be silently reset), but they cannot verify that the attention percentage a browser reports actually came from a real, live camera check. That verification happens entirely client-side, which is an inherent characteristic of any browser-based, unauthenticated verification flow like this one, not something rules alone can close. A determined person with a scripted client could therefore obtain coupons without really watching the video. Treat the reward as a low-value incentive: keep the discount modest, use WooCommerce’s own coupon restrictions, and enable Firebase App Check (below).
Firebase App Check is an additional layer on top of the Firestore rules above: it verifies that requests reaching your Firestore database are genuinely coming from your own site’s widget, not a scripted client that has simply copied your public Firebase config. This is configured per-project directly in your own Firebase Console. The plugin cannot enable or enforce it for you, so it’s a setup step you take yourself, once, per Firebase project. Once you’ve done the Console steps below, this plugin’s Settings page has a matching field so the widget can start sending App Check tokens.
Step 1: Register a reCAPTCHA v3 site key (free):
Step 2: Enable App Check in the Firebase Console:
Step 3: Give the plugin the Site Key:
Leaving the App Check Site Key field blank is safe: the plugin functions exactly as before, App Check simply isn’t used (and no App Check or reCAPTCHA scripts are loaded). This is an additional safeguard on top of the Firestore rules above, not a replacement for them; apply both.
This plugin connects to the following external services. Please review their terms and privacy policies before using the plugin.
Used to log session data and to let your server confirm that a session was verified before a coupon is issued. The Firebase JavaScript libraries are bundled with the plugin (they are not loaded from a CDN). The project used is the one you configure in Settings.
firestore.googleapis.com: a read of the session document (by session ID) in your own Firebase project, performed when a coupon is requested.Only used if you enter an App Check Site Key in Settings. The Firebase App Check library is bundled with the plugin (not loaded from a CDN). When a Site Key is set, Google reCAPTCHA v3 runs in the visitor’s browser to obtain App Check tokens, which means the visitor’s browser contacts Google. As with any request to Google, the visitor’s IP address and browser details are visible to Google.
Used for real-time face detection and attention tracking. The MediaPipe Face Mesh and Camera Utils libraries (Apache-2.0), including the WebAssembly and model files, are bundled inside the plugin in attentionverify-app/vendor/mediapipe/. Nothing is loaded from a CDN and no request is made to MediaPipe, Google or jsDelivr for face detection.
Data: detection runs entirely in the visitor’s browser. No camera images, video frames or facial measurements are transmitted anywhere.
The widget loads the DM Sans and DM Mono fonts from fonts.googleapis.com and fonts.gstatic.com. Google receives the visitor’s IP address and browser user-agent with each font request.