@extends('layouts.app') @section('title', 'Story Purchase') @section('content')

Story Purchase

Use one Instagram link for all stories. We sync stories, show only enabled ones in the wizard, detect price with AI, and send customers straight to checkout.

@php $spStatsTz = \App\Models\StoryPurchaseCheckout::displayTimezone(); $funnel = $todayFunnel ?? [ 'shopify_sends' => (int) ($shopifyCheckoutsTodayCount ?? 0), 'nmi_sends' => (int) ($nmiCheckoutsTodayCount ?? 0), 'sends' => (int) ($checkoutsTodayCount ?? 0), 'shopify_paid_count' => 0, 'nmi_paid_count' => 0, 'paid_count' => 0, 'revenue' => 0.0, 'conversion' => null, ]; @endphp
Active in app{{ $activeCount }}
Shown in link{{ $enabledCount }}
Checkouts started today{{ (int) $funnel['sends'] }} {{ (int) $funnel['shopify_sends'] }} Shopify · {{ (int) $funnel['nmi_sends'] }} NMI
Paid today{{ (int) $funnel['paid_count'] }} {{ (int) $funnel['shopify_paid_count'] }} Shopify · {{ (int) $funnel['nmi_paid_count'] }} NMI · ${{ number_format((float) $funnel['revenue'], 2) }}
Conversion today{{ ($funnel['conversion'] ?? null) !== null ? $funnel['conversion'].'%' : '—' }}

Funnel for {{ now($spStatsTz)->format('M j, Y') }} ({{ $spStatsTz }}): checkouts started = wizard sent the customer to checkout; paid = money collected. Do not treat checkout starts as Shopify sales. Abandoned Shopify checkouts are in Marketing.

@if(!empty($bestToday) && !empty($bestToday['story'])) @php $bestStory = $bestToday['story']; $bestStats = $bestToday['stats'] ?? []; $bestThumb = $bestStory->thumbnail_url ?: $bestStory->media_url; @endphp
Best today
@if($bestThumb) @else
N/A
@endif
STORY-S{{ $bestStory->id }} @if((int) ($bestStats['views'] ?? 0) > 0) {{ (int) $bestStats['views'] }} views · @endif ${{ number_format((float) ($bestStats['revenue'] ?? 0), 2) }} · {{ (int) ($bestStats['paid_count'] ?? 0) }} paid · {{ (int) ($bestStats['sends'] ?? 0) }} checkouts started @if(($bestStats['conversion'] ?? null) !== null) · {{ $bestStats['conversion'] }}% conv @endif Today’s activity only — may differ from “Top” (all-time) in the table
Today
@endif

Instagram API (Story Scheduler connection)

@csrf

Story Purchase uses the same token and Instagram User ID as Automatic Story Scheduler. Publishing stories only needs publish permissions; reading live stories for sync needs read access too.

@if(session('instagram_verify')) @php $verify = session('instagram_verify'); @endphp
{{ $verify['summary'] }}

{{ $verify['scheduler_note'] }}

@if(!empty($verify['scheduler_sufficient']))

Scheduler connection: sufficient for Story Purchase

@else

Scheduler connection: may work for publish only — fix read permissions for sync

@endif
@endif

Settings

@csrf
shopify_product_id) hidden @endif> @if($settings->shopify_product_id) Selected: {{ $settings->product_title ?: $settings->shopify_product_id }} Change @endif

When enabled, stories with a price in the caption (e.g. $399, 399$, starting at 399) are auto-shown on sync. If the caption has no price, AI reads the story image or video frame for visible price text (useful for archived videos). Seller Instagram hashtags are assigned under Setting → Sales commissions.

When enabled, stories at or above the threshold go to NMI Collect Checkout instead of Shopify. Florida IP addresses get sales tax automatically; other locations do not.

Default: $10,000. Requires NMI keys configured under Payment Links.

@if($settings->shopify_product_id)

Reset Shopify variants (testing)

Removes every story variant and images on {{ $settings->product_title ?: 'selected product' }}. STORY-DEFAULT ($100) only appears when all stories expired or after this reset. While any story variant exists, the default is removed from Shopify automatically.

@csrf
@endif

Stories

@csrf
@csrf

@if($settings->auto_wizard_on_caption_price)Stories with a price in the caption (or AI-detected price in the media) are auto-shown on sync. @endif Seller hashtags from Sales commissions also auto-show the story and assign that salesperson. Without a match, use Show below.

Reset
@if($stories->total() === 0)

No stories match these filters.

@else

Showing {{ $stories->firstItem() }}–{{ $stories->lastItem() }} of {{ $stories->total() }}

@foreach($stories as $story) @endforeach
# Preview Media Caption Performance Status Wizard
{{ $story->id }}
STORY-S{{ $story->id }}
@if($story->thumbnail_url || $story->media_url) Story preview @else
N/A
@endif
{{ $story->media_type }}
@php $displayTz = config('app.deals_display_timezone', 'America/New_York'); @endphp
{{ $story->published_at ? $story->published_at->timezone($displayTz)->format('M j, g:i A T') : '—' }}
Expires: {{ $story->expires_at ? $story->expires_at->timezone($displayTz)->format('M j, g:i A T') : '—' }} (24h after post)
{{ $story->caption ?: 'No caption' }}
@if($story->salesperson) {{ $story->salesperson->instagram_hashtag ?: $story->salesperson->full_name }} @elseif($story->has_shop_tag) Seller tag @endif @if($story->detected_price)
Price: ${{ number_format((float) $story->detected_price, 2) }}
@endif
@php $perf = $story->performance ?? []; @endphp
@if(!empty($perf['is_best_today'])) Today @endif @if(!empty($perf['is_top'])) Top @endif
{{ (int) ($perf['views'] ?? 0) }} views · {{ (int) ($perf['sends'] ?? 0) }} checkouts started · {{ (int) ($perf['paid_count'] ?? 0) }} paid
${{ number_format((float) ($perf['revenue'] ?? 0), 2) }} @if(($perf['conversion'] ?? null) !== null) · {{ $perf['conversion'] }}% conv @endif
@php $convBar = min(100, max(0, (float) ($perf['conversion'] ?? 0))); @endphp
{{ $story->is_active ? 'Active' : 'Inactive' }}
@csrf
@if($stories->hasPages()) @endif @endif
@push('scripts') @endpush @endsection