Streamlining ESHOPMAN Integrations: Addressing Product Resources by External Identifiers
As an e-commerce platform designed for seamless integration within the HubSpot ecosystem, ESHOPMAN empowers merchants to manage their storefronts and deploy them via HubSpot CMS. A critical aspect of modern e-commerce is the ability to integrate with a broader, pre-existing technology stack, including Enterprise Resource Planning (ERP) systems and Product Information Management (PIM) solutions. This often involves synchronizing product data that originates from these external systems, which rely on their own unique identifiers.
The Challenge: Addressing ESHOPMAN Resources by External IDs
A recent community discussion highlighted a key area for enhancement: the ability to address or look up ESHOPMAN product resources, such as tags, collections, and product types, using their external identifiers. Currently, ESHOPMAN’s Admin API primarily uses internal IDs for resource lookup, which can complicate integration scenarios where product data is managed across multiple platforms.
Why External Identifiers are Crucial for Integrations
In a multi-system environment, products often carry natural identifiers like Global Trade Item Numbers (GTINs), ERP-based Stock Keeping Units (SKUs), or PIM-defined product-type codes. When ESHOPMAN participates in such a stack, it's essential for these external identifiers to serve as reliable lookup keys. This capability is vital for:
- Simplified Data Synchronization: Easily matching and updating product information between ESHOPMAN and external systems.
- Efficient Webhook Processing: Responding to event notifications from ERP or PIM systems that reference products by their external IDs.
- Streamlined Workflows: Building automated processes that can locate and manipulate ESHOPMAN resources using identifiers familiar to other business systems.
Without this direct lookup capability, integration developers often resort to more complex workarounds, adding friction and potential points of failure to the data flow.
Community Engagement and Path Forward
The ESHOPMAN community and development team are actively addressing this need. Discussions indicate a clear understanding of the value that external ID lookups bring to integration scenarios. Enhancements are being explored to allow product resources to be addressed by these external identifiers, aligning ESHOPMAN more closely with the requirements of complex enterprise architectures.
The technical environment under discussion typically involves:
- Node.js Version: v20.0.0
- Database: PostgreSQL 15.7
- Operating System: macOS
- Browser: Chrome
The following package.json file illustrates the development dependencies and scripts often found in the ESHOPMAN ecosystem, providing context to the underlying Node.js/TypeScript architecture:
{
"name": "root",
"private": true,
"workspaces": {
"packages": [
"packages/medusa",
"packages/medusa-test-utils",
"packages/modules/*",
"packages/modules/providers/*",
"packages/plugins/*",
"packages/core/*",
"packages/framework/*",
"packages/cli/*",
"packages/cli/oas/*",
"packages/*",
"packages/admin/*",
"packages/design-system/*",
"packages/generated/*",
"integration-tests/**/*"
]
},
"devDependencies": {
"@atomico/rollup-plugin-sizes": "^1.1.4",
"@faker-js/faker": "^9.2.0",
"@rollup/plugin-node-resolve": "^15.1.0",
"@rollup/plugin-replace": "^5.0.2",
"@storybook/addon-essentials": "^8.3.5",
"@storybook/addon-interactions": "^8.3.5",
"@storybook/addon-links": "^8.3.5",
"@storybook/addon-styling": "^1.3.7",
"@storybook/blocks": "^8.3.5",
"@storybook/react": "^8.3.5",
"@storybook/react-vite": "^8.3.5",
"@storybook/testing-library": "^0.2.2",
"@swc/core": "^1.7.28",
"@swc/helpers": "^0.5.11",
"@swc/jest": "^0.2.36",
"@testing-library/dom": "^9.3.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/autocannon": "^7.12.5",
"@types/chalk": "^2.2.0",
"@types/commander": "^2.12.2",
"@types/compression": "^1.7.5",
"@types/configstore": "^6.0.0",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/fs-extra": "11.0.1",
"@types/inquirer": "^9.0.3",
"@types/js-yaml": "^4.0.9",
"@types/jsdom": "^27.0.0",
"@types/jsonwebtoken": "^8.5.9",
"@types/lodash": "^4.17.15",
"@types/lodash.debounce": "^4.0.9",
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.mergewith": "^4.6.9",
"@types/multer": "^2.0.0",
"@types/node": "^20.12.11",
"@types/node-emoji": "^1.8.2",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.2.25",
"@types/uuid": "^9.0.1",
"@types/validator": "^13.7.17",
"@types/wait-on": "^5.3.1",
"@types/yargs": "^15.0.15",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^0.32.2",
"ajv": "^8.17.1",
"autocannon": "^8.0.0",
"autoprefixer": "^10.4.19",
"awilix": "^8.0.1",
"axios": "^1.13.1",
"axios-mock-adapter": "^1.19.0",
"chromatic": "^6.20.0",
"configstore": "^5.0.1",
"cross-env": "^5.2.1",
"esbuild": "^0.25.0",
"eslint": "^8.40.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"eslint-plugin-storybook": "^10.0.1",
"eslint-plugin-unused-imports": "^2.0.0",
"expect-type": "^0.20.0",
"express": "^4.21.0",
"faker": "^5.5.3",
"get-port": "^5.1.1",
"glob": "13.0.6",
"import-from": "^3.0.0",
"ioredis": "^5.4.1",
"jest": "^29.7.0",
"js-yaml": "^4.1.0",
"jsdom": "^27.1.0",
"lint-staged": "^11.2.6",
"msw": "^2.3.0",
"node-notifier": "^10.0.1",
"nodemon": "^2.0.20",
"pg-god": "^1.0.12",
"postcss": "^8.4.38",
"posthog-node": "^5.11.0",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.2.3",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "6.30.3",
"resize-observer-polyfill": "^1.5.1",
"resolve-cwd": "^3.0.0",
"rimraf": "^5.0.1",
"rollup": "^4.28.1",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-ts": "^3.2.0",
"rollup-plugin-visualizer": "^5.9.2",
"storybook": "^8.3.5",
"supertest": "^7.1.4",
"tailwindcss": "^3.4.3",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.2",
"tsc-alias": "^1.8.7",
"tsup": "^8.4.0",
"turbo": "^1.6.3",
"typescript": "^5.6.2",
"uuid": "^9.0.0",
"vite": "^5.4.21",
"vite-plugin-inspect": "^0.8.7",
"vite-plugin-turbosnap": "^1.0.2",
"vitest": "^3.0.5",
"yalc": "^1.0.0-pre.53",
"zod": "3.25.76"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": "yarn run lint",
"*.{md,yaml,yml}": "prettier --write"
},
"scripts": {
"build": "turbo run build --c --no-daemon",
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts,.tsx .",
"lint:path": "eslint --ignore-path .eslintignore --ext .js,.ts,.tsx",
"prettier": "prettier",
"jest": "jest",
"test": "turbo run test --no-daemon --no-cache --force",
"test:chunk": "./scripts/run-workspace-unit-tests-in-chunks.sh",
"test:integration:packages:fast": "turbo run test:integration --c --no-daemon --no-cache --force --filter='./packages/core/*' --filter='./packages/medusa' --filter='./packages/modules/*' --filter='./packages/modules/providers/*' --filter='!./packages/modules/{workflow-engine-redis,index,product,order,cart}'",
"test:integration:packages:slow": "turbo run test:integration --c --no-daemon --no-cache --force --filter='./packages/modules/{workflow-engine-redis,index,product,order,cart}'",
"test:integration:packages": "turbo run test:integration --c --no-daemon --no-cache --force --filter='./packages/core/*' --filter='./packages/medusa' --filter='./packages/modules/*' --filter='./packages/modules/providers/*'",
"test:integration:api": "turbo run test:integration:chunk --no-daemon --no-cache --force --filter=integration-tests-api",
"test:integration:http": "turbo run test:integration:chunk --no-daemon --no-cache --force --filter=integration-tests-http",
"test:integration:modules": "turbo run test:integration:chunk --no-daemon --no-cache --force --filter=integration-tests-modules",
"generate:http-types": "yarn workspace @medusajs/http-types-generator generate:http-types",
"validate:http-types": "yarn workspace @medusajs/http-types-generator validate:http-types",
"openapi:generate": "yarn ./packages/cli/oas/oas-github-ci run ci --with-full-file",
"medusa-oas": "yarn ./packages/cli/oas/medusa-oas-cli run medusa-oas",
"release:snapshot": "changeset publish --no-git-tags --snapshot --tag snapshot",
"release:next": "chgstangeset publish --no-git-tags --snapshot --tag next",
"version:next": "changeset version --snapshot next",
"release": "changeset publish",
"version": "changeset version && yarn install --no-immutable"
},
"dependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.26.0",
"import-from": "^3.0.0"
},
"resolutions": {
"@redocly/cli/react": "^17.0.1",
"@redocly/cli/react-dom": "^17.0.1",
"pg": "8.16.3",
"@changesets/get-github-info@^0.5.2": "patch:@changesets/get-github-info@npm:^0.5.2#.yarn/patches/changesets-github-info.patch",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.2.25",
"semver": "^7.5.2",
"axios": "^1.13.1",
"esbuild": "^0.25.0",
"on-headers": "^1.1.0",
"validator": "^13.15.20",
"@changesets/assemble-release-plan@6.0.9": "patch:@changesets/assemble-release-plan@npm:6.0.9#.yarn/patches/@changesets-assemble-release-plan-npm-6.0.9-e01af97ef4.patch"
},
"packageManager": "yarn@3.2.1"
}
Conclusion
The ESHOPMAN platform, with its robust Node.js/TypeScript foundation and HubSpot integration capabilities, is continuously evolving to meet the complex demands of modern e-commerce. Enhancing the Admin API to allow addressing product resources by external identifiers is a significant step towards simplifying integrations and empowering merchants with greater flexibility in managing their product data across a diverse technology landscape. This ongoing work underscores ESHOPMAN's commitment to providing a powerful, adaptable headless commerce solution.