# mood.cards — Complete LLM Integration Guide ## Overview mood.cards is a lightweight contextual feedback engine for web applications. It captures user mood/rating at specific moments with optional comments, enriched by a JSON context payload. The widget renders as a non-intrusive card that appears near the user's action. Key properties: - No cookies, no IP logging, no GDPR-heavy requirements - No cookie consent banner needed - Anonymous UUID stored in localStorage for deduplication only - Zero required changes to host codebase beyond a script tag - Widget uses Shadow DOM — never breaks host site styles - All errors are silently caught — never breaks the host site ## Installation Place before closing tag: ```html ``` - Replace MC_YOUR_KEY with your project's API key (format: MC_ followed by 8 uppercase alphanumeric characters) - The script loads asynchronously and never blocks page rendering - API keys are generated when creating a project in the mood.cards dashboard ## API Reference ### MoodCards.show(triggerKey, options?) Show a triggered feedback card. Parameters: - triggerKey (string, required): The card's trigger key as configured in the dashboard. Format: developer-defined string, often prefixed with tr_ (e.g., 'tr_k4x9mf2a' or 'checkout_flow') - options (object, optional): - context (any): Client-owned data stored with the submission. Can be any JSON-serializable value — objects, strings, numbers. Merged with global context set via setContext(). Inline context wins on key conflicts. - anchor (string): CSS selector for an element to position the card near. Overrides global anchor and card config anchor. Returns: void Example: ```javascript // Basic trigger MoodCards.show('checkout_flow'); // With context and anchor MoodCards.show('checkout_flow', { context: { user_plan: 'pro', cart_value: 149.99 }, anchor: '#checkout-btn' }); // Context can be any type MoodCards.show('checkout_flow', { context: 'quick feedback' }); ``` ### MoodCards.trigger(triggerKey, options?) Alias for MoodCards.show(). Identical behavior. ### MoodCards.setContext(obj) Set global context that is included with every submission. Parameters: - obj (any): Context data. Pass null to clear. Merging behavior: When both global context and inline context (via show()) are objects, they are merged with inline keys winning on conflict. If either is not an object, inline wins entirely. Example: ```javascript // Set once, applies to all subsequent submissions MoodCards.setContext({ app_version: '2.1', environment: 'production' }); // This submission will include { app_version: '2.1', environment: 'production', user_plan: 'pro' } MoodCards.show('feature_feedback', { context: { user_plan: 'pro' } }); ``` ### MoodCards.setAnchor(selector) Set default CSS selector for positioning triggered cards. Parameters: - selector (string): CSS selector (e.g., '#my-button', '.action-panel') This is overridden by: - Inline anchor in show() options - Per-card anchor configured in the dashboard Example: ```javascript MoodCards.setAnchor('#main-toolbar'); MoodCards.show('toolbar_feedback'); // Card appears near #main-toolbar ``` ### MoodCards.reset() Clear all visibility suppression state from localStorage and sessionStorage. Useful for testing — makes all cards show again as if the user has never seen them. ### MoodCards.destroy() Remove all rendered cards from the DOM and clear internal state. Cards can be re-triggered after calling this. ## Card Types ### Triggered Cards - Appear on demand when MoodCards.show() is called - Start as a small preview bubble (icon + question hint) near the anchor element - Expand to full interactive card on hover or click - Auto-dismiss after a configurable timeout (default: 8 seconds) if the user doesn't interact - Respect visibility settings (once, cooldown, session, always) - Visibility is checked client-side BEFORE any API call — suppressed cards cause zero network requests ### Persistent Cards - Appear automatically as a small "Feedback" pill in the bottom-right corner - Always available, never intrusive - Click to expand, close to collapse back to pill - After submitting feedback, auto-collapses back to pill (ready for next use) - No trigger code needed — configured entirely in the dashboard - Visibility setting typically set to "always" ## Rating Types Configured per card in the dashboard: - stars: 5-star rating (1-5) - emoji: 5 emoji faces from angry to love (mapped to 1-5) - thumbs: thumbs down (1), neutral (3), thumbs up (5) All ratings are stored as integers 1-5 regardless of display type. ## Visibility & Suppression Controls how often a card shows to the same user. Checked client-side via localStorage/sessionStorage BEFORE any API call. - always: Shows every time triggered. No suppression. - once: Shows until the user interacts. After interaction, permanently suppressed (localStorage flag). - session: Shows once per browser session. Resets when session ends (sessionStorage). - cooldown: Shows once, then suppressed for N days (configurable cooldown_days). Uses localStorage timestamp. When suppressed, MoodCards.show() silently returns without making any API calls or rendering anything. ## Positioning System Triggered cards use a smart positioning algorithm to find the best spot near the user's action. Anchor resolution priority (first match wins): 1. Inline anchor: MoodCards.show('key', { anchor: '#btn' }) 2. Global anchor: MoodCards.setAnchor('#btn') 3. Card config anchor: set in the dashboard per card 4. Last click position: automatically tracked 5. Bottom-right corner: fallback when nothing else is available The positioning algorithm: - Tries 6 candidate positions around the anchor (below, above, right, left, below-right, above-right) - If the anchor is inside an .mc-avoid zone, adds 4 escape candidates at the zone edges - Scores each position based on: overlap with .mc-avoid zones, overlap with interactive elements, available free space, viewport fit - Picks the highest-scoring position ### Avoid Zones Add class="mc-avoid" to any HTML element that cards should not overlap: ```html ``` The card will automatically find a position that doesn't overlap these elements. No JavaScript configuration needed — just the CSS class. Additional avoid zones can be configured per card in the dashboard using CSS selectors. ## Context vs Meta Two JSON fields are stored with each submission: - context: Client-owned data. Set by the developer via setContext() or show() options. Stored untouched. Use for: user plan, feature flags, cart value, A/B test variant, etc. - meta: Internal mood.cards data. Automatically collected. Contains: url, path, referrer, page title, viewport dimensions, timestamp, card position info. Never modified by developers. ## Card Configuration Options Set in the mood.cards dashboard per card: - allow_comment (boolean): Show a comment textarea after rating. Default: false. - auto_dismiss_seconds (integer): Seconds before auto-dismissing a triggered card. Default: 8. Set to 0 to disable. - hide_branding (boolean): Hide "Powered by mood.cards" footer. Premium feature. ## Common Integration Patterns ### After a feature action ```javascript document.getElementById('generate-btn').addEventListener('click', () => { // ... your feature logic ... // Ask for feedback after the action setTimeout(() => { MoodCards.show('generate_feature', { anchor: '#generate-btn', context: { feature: 'generate', result: 'success' } }); }, 2000); // Small delay so user sees the result first }); ``` ### Checkout or purchase flow ```javascript // After successful checkout MoodCards.setContext({ order_id: order.id, total: order.total }); MoodCards.show('post_checkout', { anchor: '#order-confirmation' }); ``` ### Onboarding completion ```javascript // After user completes onboarding MoodCards.show('onboarding_complete', { context: { steps_completed: 5, time_spent_seconds: 180 } }); ``` ### Global context for all pages ```javascript // Set once on page load MoodCards.setContext({ user_plan: currentUser.plan, app_version: APP_VERSION, locale: navigator.language }); ``` ## Debug Mode For development and troubleshooting, replace mc.js with mc_debug.js: ```html ``` Debug mode provides: - [MoodCards] prefixed console logs for the full lifecycle: init, config cache state, card processing, show() decisions, positioning, rating selection, API calls, pings - Red dashed outlines around all .mc-avoid elements for visual debugging - Unminified source code for inspection - No functional differences from production — safe to use during development Remember to switch back to mc.js for production. ## Config Caching mc.js caches the card configuration in localStorage: - First visit: fetches config from API, caches with MD5 hash - Return visits within 1 hour: uses cache, zero API calls - After 1 hour: uses cache immediately, then background-checks the hash after 3-5 seconds - Hash mismatch: silently refreshes the config This means card configuration changes in the dashboard take up to ~1 hour to propagate to active users. ## Troubleshooting Card not showing? - Check visibility mode — it may be suppressed. Call MoodCards.reset() to clear. - Check the browser console with mc_debug.js for shouldShow() logs. - Ensure the trigger key matches exactly (case-sensitive). Card in wrong position? - Use mc_debug.js to see positioning logs with candidate scores. - Check .mc-avoid zones are correctly placed. - Try setting an explicit anchor: MoodCards.show('key', { anchor: '#element' }) Card overlapping UI elements? - Add class="mc-avoid" to the elements that should be protected. - Configure avoid zones in the dashboard for server-side selectors. Submissions not appearing in dashboard? - Check allowed origins in project settings. Empty = all origins accepted. - Verify API key matches (check X-MC-Key header in network tab). - Check rate limits: 20 submissions/minute per IP.