← back to Handbag Auth Nextjs

scripts/handbagAffiliateSignup.ts

182 lines

// Puppeteer-based affiliate signup automation for handbag merchants
// Pre-fills signup forms with your business information

import type { AffiliateSignupProfile } from "../src/types/handbagRss";

// Your business profile for affiliate signups
const profile: AffiliateSignupProfile = {
  contactName: "Steve Abrams",
  company: "Handbag Finder",
  email: "steve@designerwallcoverings.com",
  websites: ["https://your-handbag-app.com"],
  description:
    "We operate a luxury handbag price-tracking and authentication app with marketplace comparison, affiliate partnerships, and verified product data.",
};

interface SignupConfig {
  signupUrl: string;
  selectors: {
    name?: string;
    company?: string;
    email?: string;
    website?: string;
    description?: string;
    submitButton?: string;
  };
}

import puppeteer from "puppeteer";

export async function openHandbagAffiliateSignup(config: SignupConfig) {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: { width: 1280, height: 900 }
  });

  const page = await browser.newPage();

  console.log(`Opening ${config.signupUrl}...`);
  await page.goto(config.signupUrl, { waitUntil: "networkidle2" });

  const sel = config.selectors;

  // Fill in form fields
  if (sel.name) {
    try {
      await page.waitForSelector(sel.name, { timeout: 5000 });
      await page.type(sel.name, profile.contactName);
      console.log("✓ Filled name field");
    } catch (err) {
      console.warn(`Could not fill name field: ${sel.name}`);
    }
  }

  if (sel.company) {
    try {
      await page.waitForSelector(sel.company, { timeout: 5000 });
      await page.type(sel.company, profile.company);
      console.log("✓ Filled company field");
    } catch (err) {
      console.warn(`Could not fill company field: ${sel.company}`);
    }
  }

  if (sel.email) {
    try {
      await page.waitForSelector(sel.email, { timeout: 5000 });
      await page.type(sel.email, profile.email);
      console.log("✓ Filled email field");
    } catch (err) {
      console.warn(`Could not fill email field: ${sel.email}`);
    }
  }

  if (sel.website) {
    try {
      await page.waitForSelector(sel.website, { timeout: 5000 });
      await page.type(sel.website, profile.websites[0]);
      console.log("✓ Filled website field");
    } catch (err) {
      console.warn(`Could not fill website field: ${sel.website}`);
    }
  }

  if (sel.description) {
    try {
      await page.waitForSelector(sel.description, { timeout: 5000 });
      await page.type(sel.description, profile.description ?? "");
      console.log("✓ Filled description field");
    } catch (err) {
      console.warn(`Could not fill description field: ${sel.description}`);
    }
  }

  // Highlight submit button but DON'T auto-submit
  if (sel.submitButton) {
    try {
      await page.evaluate((btnSel) => {
        const btn = document.querySelector(btnSel);
        if (btn) {
          (btn as HTMLElement).style.outline = "4px solid #ff7b00";
          (btn as HTMLElement).style.outlineOffset = "2px";
          btn.scrollIntoView({ behavior: "smooth", block: "center" });
        }
      }, sel.submitButton);
      console.log("✓ Submit button highlighted (review and click manually)");
    } catch (err) {
      console.warn("Could not highlight submit button");
    }
  }

  console.log("\n=== Form Pre-filled ===");
  console.log("Review the information and submit manually.");
  console.log("Browser will stay open for your review.\n");
}

// Example configurations for popular handbag merchants
const merchantConfigs: Record<string, SignupConfig> = {
  fashionphile: {
    signupUrl: "https://fashionphile.com/affiliate-signup",
    selectors: {
      name: 'input[name="name"]',
      email: 'input[name="email"]',
      company: 'input[name="company"]',
      website: 'input[name="website"]',
      description: 'textarea[name="description"]',
      submitButton: 'button[type="submit"]',
    },
  },
  rebag: {
    signupUrl: "https://rebag.com/affiliates",
    selectors: {
      name: 'input[name="contact_name"]',
      email: 'input[name="email"]',
      website: 'input[name="website"]',
      submitButton: 'button.submit',
    },
  },
  therealreal: {
    signupUrl: "https://therealreal.com/affiliate-program",
    selectors: {
      name: 'input[id="name"]',
      email: 'input[id="email"]',
      company: 'input[id="company"]',
      website: 'input[id="website"]',
      submitButton: 'button.btn-primary',
    },
  },
};

// CLI usage
const isMainModule = import.meta.url === `file://${process.argv[1]}`;

if (isMainModule) {
  const merchant = process.argv[2];

  if (!merchant) {
    console.log("Usage: ts-node scripts/handbagAffiliateSignup.ts <merchant>");
    console.log("\nAvailable merchants:");
    Object.keys(merchantConfigs).forEach((key) => {
      console.log(`  - ${key}`);
    });
    process.exit(1);
  }

  const config = merchantConfigs[merchant.toLowerCase()];
  if (!config) {
    console.error(`Unknown merchant: ${merchant}`);
    console.log("\nAvailable merchants:");
    Object.keys(merchantConfigs).forEach((key) => {
      console.log(`  - ${key}`);
    });
    process.exit(1);
  }

  openHandbagAffiliateSignup(config).catch((err) => {
    console.error("Error:", err);
    process.exit(1);
  });
}

export { profile, merchantConfigs };