Auth Modal
Marketing Hub (B2B)

Marketing Hub bridge (B2B)

Project owners use Marketing powered by Web5 Nexus (opens in a new tab) to create an App, store their Web3Auth BYOK clientId, and copy a public API key (pk_). Host apps ship Auth Modal / headless with that key. End users never see Marketing — their email and EVM/BTC wallets land in the owner’s Users dashboard.

Model

Marketing conceptRole
ProjectCustomer workspace
AppNamed product under the project
App pk_Public key for Auth Config + identify
UsersEnd-users filtered by App; wallets in data.wallets
Web5 MAWUnique auth_connect users per App per UTC month

Web3Auth stays BYOK — one clientId per App in App settings. No key rotation / fee-dodging pools.

Owner setup

  1. Open Marketing → your ProjectSettings → Apps
  2. Create App (name = product name)
  3. Set Web3Auth client ID (+ optional Bitcoin flag)
  4. Copy the auto-created public key (pk_…)
  5. Ship the SDK with baseUrl + that pk_

Host SDK

npm i @web5nexus/authmodal-marketing @web5nexus/authmodal-react \
  @web5nexus/authmodal-web3auth @web5nexus/authmodal-core
import { AuthModalProvider, ConnectButton } from '@web5nexus/authmodal-react'
import { web3auth } from '@web5nexus/authmodal-web3auth'
import { withMarketingAuth } from '@web5nexus/authmodal-marketing'
import '@web5nexus/authmodal-react/styles.css'
 
const marketing = {
  baseUrl: process.env.NEXT_PUBLIC_WEB5_MARKETING_URL!,
  apiKey: process.env.NEXT_PUBLIC_WEB5_MARKETING_PK!,
}
 
export default async function App() {
  const config = await withMarketingAuth(
    {
      adapters: [],
      chains: [1, 8453],
      transport: {
        mode: 'custom',
        chainId: 1,
        rpcUrl: 'https://rpc.ankr.com/eth',
      },
    },
    {
      ...marketing,
      createWeb3AuthAdapter: ({ clientId, network }) =>
        web3auth({
          clientId,
          network: (network as 'sapphire_mainnet') ?? 'sapphire_mainnet',
        }),
    },
  )
 
  return (
    <AuthModalProvider {...config}>
      <ConnectButton />
    </AuthModalProvider>
  )
}

Identify-only (custom UI / headless)

import { createMarketingIdentify } from '@web5nexus/authmodal-marketing'
 
createAuthModal({
  /* adapters, chains, transport… */
  onSession: createMarketingIdentify({
    baseUrl: process.env.NEXT_PUBLIC_WEB5_MARKETING_URL!,
    apiKey: process.env.NEXT_PUBLIC_WEB5_MARKETING_PK!,
  }),
})

On connect and reconnect, the SDK posts POST /api/client/identify with email + wallet_address + multi-chain wallets[]. Marketing records an auth_connect event for MAW.

Auth Config

GET /api/client/auth/config (Bearer App pk_) returns:

{
  "appId": "12",
  "appName": "My Dapp",
  "projectId": 1,
  "web3auth": { "clientId": "…", "network": "sapphire_mainnet" },
  "theme": { "appName": "My Dapp" },
  "bitcoin": { "enabled": false }
}

Demo

Auth Modal Vite lab (packages/demo): open Marketing Hub panel, paste API base URL + App pk_, enable identify, then connect — Users appear in that Marketing App (also via VITE_MARKETING_BASE_URL / VITE_MARKETING_PK).

Security

  • Browser: App pk_ only
  • Never ship Marketing sk_ in client bundles
  • End-user PII lives in the owner’s Marketing project

Related