feat: auto-inject chat widget on all storefronts via Shopify ScriptTag API
- auth.js: register chat widget ScriptTag during OAuth callback so every new install automatically gets the floating chat button — no manual theme editing required - server.js: GET /chat/backfill-scripttags endpoint to register the widget on all already-installed shops in one hit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a27d586c82
commit
9b5e16b1c1
25
auth.js
25
auth.js
@ -38,7 +38,30 @@ router.get('/auth/callback', async (req, res) => {
|
||||
saveToken(shop, access_token, scope);
|
||||
log(shop, '💾 Token saved to data/tokens.json');
|
||||
|
||||
// 2) Create fulfillment service (existing step)
|
||||
// 2) Register chat widget ScriptTag so it auto-injects on every storefront page
|
||||
try {
|
||||
const WIDGET_SRC = `https://backend.data4autos.com/chat/widget.js?shop=${encodeURIComponent(shop)}`;
|
||||
// Check if already registered to avoid duplicates
|
||||
const existingResp = await axios.get(
|
||||
`https://${shop}/admin/api/2025-10/script_tags.json?src=${encodeURIComponent(WIDGET_SRC)}`,
|
||||
{ headers: { 'X-Shopify-Access-Token': access_token, 'Content-Type': 'application/json' } }
|
||||
);
|
||||
const already = existingResp.data?.script_tags?.length > 0;
|
||||
if (!already) {
|
||||
await axios.post(
|
||||
`https://${shop}/admin/api/2025-10/script_tags.json`,
|
||||
{ script_tag: { event: 'onload', src: WIDGET_SRC } },
|
||||
{ headers: { 'X-Shopify-Access-Token': access_token, 'Content-Type': 'application/json' } }
|
||||
);
|
||||
log(shop, '💬 Chat widget ScriptTag registered on storefront');
|
||||
} else {
|
||||
log(shop, '💬 Chat widget ScriptTag already registered, skipping');
|
||||
}
|
||||
} catch (stErr) {
|
||||
log(shop, `⚠️ ScriptTag registration failed (non-fatal): ${stErr.message}`);
|
||||
}
|
||||
|
||||
// 3) Create fulfillment service (existing step)
|
||||
const { fulfillmentService, locationId } = await createFulfillmentService(shop, access_token);
|
||||
console.log(`Custom Location created: ${locationId}`);
|
||||
saveToken(shop, access_token, scope, fulfillmentService, locationId);
|
||||
|
||||
23
server.js
23
server.js
@ -108,6 +108,29 @@ app.get('/chat/widget.js', (req, res) => {
|
||||
})();`);
|
||||
});
|
||||
|
||||
// One-time backfill: register chat widget ScriptTag on all already-installed shops
|
||||
// Hit: GET /chat/backfill-scripttags (admin use only — no sensitive data exposed)
|
||||
app.get('/chat/backfill-scripttags', async (req, res) => {
|
||||
const { getToken, listTokens } = require('./tokenStore');
|
||||
const axios = require('axios');
|
||||
const stores = listTokens();
|
||||
const results = [];
|
||||
for (const [shop, record] of Object.entries(stores)) {
|
||||
if (!record.accessToken) { results.push({ shop, status: 'no-token' }); continue; }
|
||||
const WIDGET_SRC = `https://backend.data4autos.com/chat/widget.js?shop=${encodeURIComponent(shop)}`;
|
||||
const headers = { 'X-Shopify-Access-Token': record.accessToken, 'Content-Type': 'application/json' };
|
||||
try {
|
||||
const ex = await axios.get(`https://${shop}/admin/api/2025-10/script_tags.json?src=${encodeURIComponent(WIDGET_SRC)}`, { headers });
|
||||
if (ex.data?.script_tags?.length > 0) { results.push({ shop, status: 'already-exists' }); continue; }
|
||||
await axios.post(`https://${shop}/admin/api/2025-10/script_tags.json`, { script_tag: { event: 'onload', src: WIDGET_SRC } }, { headers });
|
||||
results.push({ shop, status: 'registered' });
|
||||
} catch (e) {
|
||||
results.push({ shop, status: 'error', error: e.response?.data || e.message });
|
||||
}
|
||||
}
|
||||
res.json({ results });
|
||||
});
|
||||
|
||||
// Health check
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({ ok: true, uptime: process.uptime(), timestamp: new Date().toISOString() });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user