AutoDrop — One-click Product • Reel • Page
Skip to content
1) Find winning products
Rainforest API
Search Amazon via your secure worker. We score demand, competition, margin, and seasonality into a WinScore.
2) Generate product page
A11y • SEO • JSON-LD
Preview a lean, fast product page. Download a single HTML file and deploy anywhere.
3) Craft Reel script & caption
Short-form best practices
Create a native-feeling plan: hook, beats, caption, hashtags. Upload a video or publish an image post.
4) Growth & extras
A/B • Email • UTM • Policies
Email capture embed
Paste into the exported page.
Policies
Generate Terms/Privacy/Returns stubs.
${thumbs}
${esc(p.title)}
${esc(p.subtitle)}
Limited stock — today’s price secured at checkout.
${priceTag}
Buy now
${(p.badges||[]).map(b=>`${esc(b)}`).join("")}
${esc(p.shipping_note)} • ${esc(p.guarantee)}
`;
}
// ---------- REELS ----------
$("btnBuildReel").addEventListener("click", ()=>{
if(!state.selected){ toast("Pick a product first",false); return }
const tone = $("tone").value;
const bullets = (state.selected.bullets||[]).slice(0,3);
const hook = chooseHook(state.selected,tone);
const beats = [
`Hook: ${hook}`,
"Show the core benefit in 3 seconds",
"Demonstrate a before/after use case",
"Overlay 2–3 micro-features with text",
"CTA: Tap link in bio"
];
const script = beats.map((b,i)=>`[0:${String(i*3).padStart(2,'0')}] ${b}`).join("\n");
const tags = buildHashtags(state.selected);
const caption = `${hook}\n\nWhy it slaps:\n• ${bullets[0]||"Instant upgrade"}\n• ${bullets[1]||"Easy to use"}\n• ${bullets[2]||"Built to last"}\n\nTap the link in bio to get yours.\n\n${tags.join(" ")}`;
$("scriptOut").value=script; $("hashtagsOut").value=tags.join(" "); $("captionOut").value=caption;
$("charCount").textContent = caption.length + " / 2200";
state.reelPlan = { script, caption, tags }; setStatus("Reel plan generated"); toast("Reel plan ready");
});
function chooseHook(p,t){ const t4=(p.title||"").split(" ").slice(0,4).join(" ");
const v=[`Stop scrolling — this ${t4} changes everything.`,`${t4} you’ll actually use daily.`,`POV: you just saved $20 with this ${t4}.`,`Why everyone’s grabbing this ${t4}.`];
return v[Math.floor(Math.random()*v.length)];
}
function buildHashtags(p){
const base=["#onlineshopping","#dailyfinds","#musthave","#viralproducts","#useful"];
const cat=(p.category||"").toLowerCase();
const niche = cat.includes("pet")?["#petproducts","#dogsoftiktok","#petparent"]
:cat.includes("kitchen")?["#kitchenfinds","#homecafe","#coffeelover"]
:["#giftideas","#amazonfinds","#homefinds"];
return [...niche,...base].slice(0,12);
}
// ---------- INSTAGRAM ----------
$("btnConnectIg").addEventListener("click",()=>{ location.href="/api/instagram/start" });
$("btnPublishIg").addEventListener("click", async ()=>{
if(!state.selected||!state.reelPlan){ toast("Pick product + build reel plan first",false); return }
$("igStatus").textContent="Publishing…"; startBar();
try{
let uploadUrl=null; const file=$("reelFile").files[0];
if(file){
const fd=new FormData(); fd.append("file",file);
const up=await fetch("/api/upload",{method:"POST",body:fd});
if(!up.ok) throw new Error("Upload failed"); uploadUrl=(await up.json()).url;
}
const resp=await fetch("/api/instagram/publish",{method:"POST",headers:{"Content-Type":"application/json"},
body:JSON.stringify({caption:$("captionOut").value,product_image:state.selected.image,media_type:file?"REELS":"IMAGE",video_url:uploadUrl})});
const j=await resp.json(); if(!resp.ok) throw new Error(j.error||"Publish failed");
$("igStatus").textContent="Published! Media ID: "+j.media_id; toast("Instagram published"); setStatus("Instagram published");
}catch(e){ console.error(e); $("igStatus").textContent="Error: "+e.message; toast(e.message,false) }
finally{ endBar(); resetBar() }
});
// ---------- STRIPE ----------
$("btnStripe").addEventListener("click", async ()=>{
try{
if(!state.selected){ toast("Pick a product first",false); return }
const cents = Math.round(Number($("price").value || state.selected.price || 0)*100);
if(!cents || cents<100){ toast("Set a valid price first",false); return }
const r=await fetch("/api/stripe/create_payment_link",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:state.selected.title||"AutoDrop Product",price_cents:cents})});
const j=await r.json(); if(!r.ok) throw new Error(j.error||"Stripe error");
$("checkoutUrl").value=j.url; $("stripeConn").textContent="Payment Link ready"; state.stripeConnected=true; toast("Stripe link created");
}catch(e){ toast(e.message,false) }
});
// ---------- GROWTH ----------
$("btnStartAB").addEventListener("click",()=>{ state.abRunning=true; toast("A/B started — rotate your hero in the export") });
$("btnUtm").addEventListener("click",()=>{ const u=buildUtmFromInputs($("checkoutUrl").value||""); $("utmOut").textContent=u; state.utm=u; });
$("btnPolicies").addEventListener("click",()=>{ alert("We’ll append Terms/Privacy/Returns placeholders to your export. Customize for your locale.") });
$("btnCopyEmbed").addEventListener("click",()=>{ navigator.clipboard.writeText($("embedOut").value).then(()=>toast("Embed copied")) });
function seedEmbed(){
$("embedOut").value =
`
`;
}
function buildUtmFromInputs(base){
try{ const u=new URL(base||"#");
const s=$("utmSource").value||"instagram", m=$("utmMedium").value||"social", c=$("utmCampaign").value||"launch";
if(base){ u.searchParams.set("utm_source",s); u.searchParams.set("utm_medium",m); u.searchParams.set("utm_campaign",c) }
return base?u.toString():base;
}catch{ return base }
}
function slugify(s){return (s||"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")}