PageSourceSearch

https://a4b.ai/assets/controllers/sourceforge_badges_controller-c2ad985a.js

js a4b.ai collected 2026-10-05 14:32:13 UTC 2,276 bytes, 54 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2import { hasAdvertisingConsent } from "controllers/iubenda_consent"
3
4// Loads SourceForge / Slashdot / Top Business Software review badges
5// only after advertising consent (Iubenda purpose 5).
6//
7// Consent category rationale: Purpose 5 (targeting & advertising)
8// rather than Purpose 4 (analytics), because SF badges are third-party
9// marketing widgets showcasing the product on a lead-generation directory
10// — they serve promotional, not measurement, purposes. Same classification
11// as the LinkedIn Insight Tag and Google Ads gtag loaders in this repo.
12//
13// GDPR-compliant flow:
14// 1. Controller connects on page load
15// 2. Checks Iubenda consent cookie for advertising permission
16// 3. Only injects third-party badge scripts if consent is granted
17// 4. When Iubenda refreshes page after consent, controller re-runs and loads scripts
18//
19// The fallback <a href> links inside .sf-root divs render unconditionally
20// in the ERB template, so dofollow backlinks remain visible to Googlebot
21// and no-consent visitors — that is the primary SEO value.
22//
23// Three SourceForge-family variants are loaded:
24//   - sf  → sourceforge.net listing
25//   - sd  → slashdot.org listing
26//   - tbs → topbusinesssoftware.com listing
27//
28// Usage: Add to the container wrapping the three .sf-root divs:
29//   data-controller="sourceforge-badges"
30//   data-sourceforge-badges-sf-id-value="<product-sf-id>"
31//
32// @see https://sourceforge.net/ (badge generator in vendor dashboard)
33export default class extends Controller {
34  static values = { sfId: String }
35  static VARIANTS = ["sf", "sd", "tbs"]
36
37  connect() {
38    if (!this.sfIdValue) return
39    if (!hasAdvertisingConsent()) return
40
41    this.constructor.VARIANTS.forEach((variant) => this.injectBadgeScript(variant))
42  }
43
44  injectBadgeScript(variant) {
45    // Guard against duplicate loading (Turbo navigation re-connects controllers)
46    if (document.querySelector(`script[data-sf-badge-variant="${variant}"]`)) return
47
48    const script = document.createElement("script")
49    script.async = true
50    script.src = `https://b.sf-syn.com/badge_js?sf_id=${this.sfIdValue}&variant_id=${variant}`
51    script.dataset.sfBadgeVariant = variant
52    document.head.appendChild(script)
53  }
54}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.