
Research
/Security News
Trivy Under Attack Again: Widespread GitHub Actions Tag Compromise Exposes CI/CD Secrets
Attackers compromised Trivy GitHub Actions by force-updating tags to deliver malware, exposing CI/CD secrets across affected pipelines.
@topsort/building-blocks
Advanced tools
Topsort's JS library for building individual and easily integratable widgets
Topsort's JS library for building individual and easily integratable widgets.
Insert a script in your site's <head> tag to load the Topsort Building Blocks library. Ensure the script has defer to load it without affecting your site load times. Replace x.y.z with the desired version, or use @latest to use the latest version of the library at all times.
<head>
<!-- The rest -->
<script
defer
src="https://unpkg.com/@topsort/building-blocks@x.y.z/dist/index.js"
></script>
</head>
After the DOM is loaded, create an instance of the TopsortBlocks library. For example:
document.addEventListener("DOMContentLoaded", async () => {
const tsBlocks = new TopsortBlocks();
});
Initialize it:
With defaults:
await tsBlocks.init({
authUrl: "https://topsort.auth.mymarketplace.com",
externalVendorId: "vendor-id-123",
});
With custom props:
await tsBlocks.init({
// auth settings
authUrl: "https://topsort.auth.mymarketplace.com",
extraAuthHeaders: {
Authorization: `Bearer api-key-123`,
},
externalVendorId: "vendor-id-123",
// if you want to use a custom target class:
promoteTargetClassName: "my-custom-promote-target",
style: {
// color RGBs acceptable in either format:
primaryColorRgb: "50, 175, 200",
secondaryColorRgb: "50, 175, 200",
fontColorRgb: [50, 175, 200],
button: {
// defaults to "sm":
borderRadius: "none" | "sm" | "full",
},
},
text: {
// defaults to "Promote":
promoteButton: "Create Campaign",
// defaults to "See Campaign":
detailButton: "View Campaign",
},
});
The authUrl is the URL to your backend endpoint that requests the JWT from the Topsort Modal Auth API and returns its response. It acts as a proxy, enhancing security by keeping your advanced API key secure and enabling you to interact with Topsort's systems.
The Modal API employs JSON Web Tokens (JWT) to validate every request made to our systems. To acquire a JWT, you'll need to hit our public Modal Auth API, supplying the vendorId used by the library. In response, we'll provide a JWT that authorizes that specific vendor to perform tasks offered by the Modal library for a restricted time period.
Here's an example on how to request a JWT:
curl --request GET \
--url https://api.topsort.com/public/v1/modal-service/auth/vendors/vendor-id \
--header 'accept: application/json' \
--header 'authorization: Bearer <YOUR_ADVANCED_API_KEY>'
Note that this request mandates the use of your ADVANCED_API_KEY as authorization.
Given that the API key allows campaign creation, deletion, catalog management, and more, it's crucial to prevent its exposure. We therefore advise our customers to establish an endpoint on their backend that makes this request.
This backend endpoint should be accessible via authUrl. In essence, the authUrl is the URL to the backend endpoint that will request the JWT from the Modal Auth API. Think of it as a proxy call!
By implementing this setup, you can safely and securely interact with Topsort's systems and manage your ad campaigns. You must set the authUrl during initialization. Optionally, you can pass headers for the request to your backend, as shown in the following example:
await tsBlocks.init({
// auth settings
authUrl: "https://topsort.auth.mymarketplace.com",
extraAuthHeaders: {
Authorization: `Bearer api-key-123`,
}
});
To put it simply, you need to make a request to ${authUrl}/auth/vendors/${vendorId} on your backend, which in turn should call our Modal Auth API at https://api.topsort.com/public/v1/modal-service/auth/vendors/${vendorId}. Your endpoint will then return whatever response it receives from our API.
To add a button that will create a campaign with all the vendor products, add the following HTML class to the element you want the button appended to:
<div class="ts-promote-shop" data-ts-shop-name="My Shop"></div>
Then simply call useShopPromotion to have the button rendered and functional, like so:
tsBlocks.useShopPromotion();
If there is no product related markup added, the only option to promote a product would be through a 'Promote My Shop' button which will add all vendor products to a campaign.
If you decide to integrate the product promotion feature, follow these steps:
In your markup, add the following HTML class and data attributes to the element(s) you want a Promote button appended to:
<div
class="ts-promote-target some-other-custom-class"
data-ts-product-id="product-id-123"
data-ts-product-name="My Product"
data-ts-product-img-url="https://picsum.photos/100"
>
...
</div>
This target class is also a static property of the TopsortBlocks class:
<div
class={`${TopsortBlocks.promoteTargetClassName} my-custom-class`}
data-ts-product-id="product-id-123"
data-ts-product-name="My Product"
data-ts-product-img-url="https://picsum.photos/100"
>
...
</div>
If you are using a custom promote target class name, use it instead:
<div
class="my-custom-promote-target my-custom-class"
data-ts-product-id="product-id-123"
data-ts-product-name="My Product"
data-ts-product-img-url="https://picsum.photos/100"
>
...
</div>
Call useProductPromotion to have the Promote buttons rendered, and each time you want to have the Promote buttons rerendered such as after navigating to a new page of products or filtering the product list:
tsBlocks.useProductPromotion();
Install the dependencies:
pnpm install
Create and set up your .env file:
cp .env.example .env
Start the development server. The console will output a clickable URL.
pnpm run start
Environment variables should not contain secrets (e.g. private API keys) since they will be injected into the published build. They are meant to change the behaviour between different environments such as calling a local, staging, or production Central Services API base URL.
To add a new env var:
Add its name to .env.example with an empty or default value:
MY_NEW_PUBLIC_VAR=
Add its name and value to your .env:
MY_NEW_PUBLIC_VAR="the actual value"
To have it injected into the app, add it to webpack.common.js in the DefinePlugin:
Remember to wrap the value in
JSON.stringify()because theDefinePlugindoes a find-and-replace and the value given to it must include actual quotes inside of the string itself.For reference, see the Tip on the Webpack DefinePlugin docs.
new webpack.DefinePlugin({
// ...the rest
MY_NEW_PUBLIC_VAR: JSON.stringify(process.env.MY_NEW_PUBLIC_VAR),
}),
To inform TypeScript of this new global variable, add it to src/types.ts under the global declaration with its type:
declare global {
// ...the rest
const MY_NEW_PUBLIC_VAR: string;
}
To inform eslint of this new global variable, add it to .eslintrc.js under globals with a readonly value (assuming it's meant to be readonly):
globals: {
// ...the rest
MY_NEW_PUBLIC_VAR: "readonly",
},
Ensure you restart your dev server so webpack can pick up the latest changes.
FAQs
Topsort's JS library for building individual and easily integratable widgets
The npm package @topsort/building-blocks receives a total of 2 weekly downloads. As such, @topsort/building-blocks popularity was classified as not popular.
We found that @topsort/building-blocks demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Attackers compromised Trivy GitHub Actions by force-updating tags to deliver malware, exposing CI/CD secrets across affected pipelines.

Security News
ENISA’s new package manager advisory outlines the dependency security practices companies will need to demonstrate as the EU’s Cyber Resilience Act begins enforcing software supply chain requirements.

Research
/Security News
We identified over 20 additional malicious extensions, along with over 20 related sleeper extensions, some of which have already been weaponized.