The widget is responsive and works in mobile WebViews:
Breakpoint
Layout Changes
< 360px
Retailer grid: 2 columns
360px+
Retailer grid: 3 columns
Touch
Larger tap targets, no hover states
WebView Configuration
For iOS:
For Android:
Testing Checklist
Before going live, test these scenarios:
Happy Paths
Error Paths
Edge Cases
FAQ
Q: How long does a sync take? A: Typically 30-90 seconds per retailer. MFA adds user interaction time.
Q: What if the user closes the widget mid-sync? A: Sync continues in background. Re-opening shows the progress view.
Q: Can users connect the same retailer account to multiple apps? A: Yes! Sync As A Service uses portable identity. One phone number = one account.
Q: What retailers are supported? A: 15+ retailers including Amazon, Walmart, Target, Costco, Kroger, Best Buy, Home Depot, Sephora, and more—with new retailers added regularly.
Q: How often does data sync automatically? A: Weekly for active users. Users can also trigger manual syncs.
Need help? Contact your Sync As A Service integration manager.
const widget = BrandclubSync.init({ ... });
widget.destroy(); // Clean up and remove widget
WIDGET STATE MACHINE
+-----------------------------------------------------------------------------+
[loading] <-- Initial state (fetching data)
|
+-- Has token + has connections -------> [connected]
+-- Has token + no connections --------> [not-connected]
+-- No token --------------------------> [not-connected]
[not-connected] --> [OAuth popup] --> [picking]
"Get Started" (retailers)
|
v
[connected] <--- sync complete -----------+
(list) <--- tap "Connect Another" ---+
| |
| "Sync All" v
| or "Sync" [credentials]
| (username/password)
| |
| v
+------------------------> [syncing] <---- MFA submitted
(progress view)
|
+---------------------+---------------------+
| | |
v v v
[completed] [mfa] [error]
OK (verify) !!
+-----------------------------------------------------------------------------+
+----------------------------------------+
| |
| [ICON] |
| |
| Connect Your Accounts |
| |
| Link your retailer accounts to |
| sync your purchase history |
| automatically |
| |
| [ Get Started ] |
| |
| Secured Connection |
| |
+----------------------------------------+
+----------------------------------------------------------------+
| sync.brandclub.com/login [X] |
+----------------------------------------------------------------+
| |
| Sync As A Service |
| |
| Sign in to continue to |
| |
| [ Your App Name ] <-- Your app name shown |
| |
| |
| Enter your phone number |
| |
| [+1 v] [ (555) 123-4567 ] |
| Phone number |
| |
| [ Continue ] |
| |
| ---------------------------------- |
| |
| By continuing, you agree to the |
| Terms of Service and Privacy Policy |
| |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
| sync.brandclub.com/login [X] |
+----------------------------------------------------------------+
| |
| <- Back |
| |
| Sync As A Service |
| |
| Enter verification code |
| |
| We sent a 6-digit code to |
| +1 (555) ***-**67 |
| |
| |
| [4] [2] [4] [2] [4] [2] |
| |
| |
| [ Verify ] |
| |
| |
| Didn't receive code? |
| Resend code (available in 30s) |
| |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
| |
| OK Signing you in... |
| |
| (popup closes) |
| |
+----------------------------------------------------------------+
+----------------------------------------+
| |
| |
| !! |
| |
| Connection Failed |
| |
| Login failed. Please check your |
| username and password. |
| |
| [ Try Again ] [ Go Back ] |
| |
| |
+----------------------------------------+
User Flow SDK Events
--------- ----------
Opens widget (no event)
|
v
Taps "Get Started" --> AUTH_REQUIRED
|
v
Completes OAuth --> (tokens provided internally)
|
v
Selects Amazon --> (no event yet)
|
v
Enters credentials --> CONNECT_STARTED { retailerId: 1, syncBatchId: "batch_123" }
|
v
MFA required --> (widget handles internally)
|
v
Enters OTP --> (widget handles internally)
|
v
Sync completes --> SYNC_COMPLETE { syncBatchId: "batch_123", ordersFound: 47 }
BrandclubSync.init({
clientId: "bc_your_app",
container: document.getElementById("widget"),
onSync: (result) => {
// Called when sync completes
console.log(`Synced! Found ${result.ordersFound} orders`);
// Fetch orders from your backend
refreshOrdersUI();
},
onEvent: (event, metadata) => {
switch (event) {
case "CONNECT_STARTED":
analytics.track("retailer_connect_started", metadata);
break;
case "SYNC_COMPLETE":
analytics.track("sync_completed", metadata);
showSuccessToast(`Found ${metadata.ordersFound} orders!`);
break;
case "SIGN_OUT":
// Clear any cached user data
clearUserSession();
break;
}
},
onExit: (metadata) => {
// User closed or cancelled
if (metadata.status === "error") {
showErrorMessage(metadata.error_message);
}
},
});
User enters wrong password
|
v
Widget shows inline error on credentials form:
"Invalid username or password. Please check and try again."
|
v
Exponential backoff kicks in:
- 1st retry: immediate
- 2nd retry: wait 5s
- 3rd retry: wait 10s
- 4th+ retry: wait 30s
|
v
User can retry or go back
User doesn't enter MFA code in time
|
v
Sync status becomes "timed_out"
|
v
Widget shows error view:
"Connection timed out. Please try again."
|
v
"Try Again" --> back to credentials form
Retailer website is having issues
|
v
Sync status becomes "error" with message
|
v
Widget shows error view:
"This retailer is temporarily unavailable. Try again in a few minutes."
|
v
User can retry later
Too many sync attempts in short period
|
v
API returns 429
|
v
Widget shows:
"Too many attempts. Please wait a minute before trying again."
Token expires during long sync
|
v
API returns 401
|
v
Widget clears session, shows not-connected
|
v
User must re-authenticate
<!-- Full width, auto height -->
<div id="widget" style="width: 100%; max-width: 480px;"></div>
<!-- The widget will request height changes via RESIZE event -->