Banner
An inline promotion that adapts to its available width.
One promotion feed for the Infinitum family. Add useful product recommendations to your own apps and websites, with no ad-network account or advertising payments.
Live previews use your product icons and active campaigns. Full-screen previews open only when you choose them.
An inline promotion that adapts to its available width.
Product assets arranged as a recommendation within your content.
A full-screen promotion at a natural break, such as after a completed activity.
A dismissible welcome promotion during your app’s launch or return experience.
Change the slot width, source app or device context. The result is a live promotion from the public API.
Loading preview…
All 16 currently Available products participate. Staff access, Beta, In development, draft and future catalog entries are excluded. Device compatibility and source-app exclusions run before rotation: iOS-only products cannot be selected for Android. Products offering Web access can appear on Android because their web version is usable there.
Each eligible product gets a turn before repeating. Spotlight, Editorial and Bold creative versions alternate across selections, using the actual product icon and catalog copy. Rotation happens on a new placement or full-screen request, not on a timer while someone is reading. Resizing preserves the current creative. When only one product qualifies it may repeat, using a different creative version.
InfinitumAdsNetworkAPI uses the space available to the ad, a coarse device-platform hint, and your app or page category. It does not identify a person, inspect browsing history, use location or infer interests. Device hints can be wrong; native apps and integrations that know the platform should pass it explicitly.
max-height selects compact below 180px and hides the ad below 110px. If the actual text still does not fit, display nothing.platform="iOS" requires iOS.category="Pets" page hint overrides that app category. This is weighted preference, not a guaranteed match.The widget follows the system light/dark preference. Set theme="light" or theme="dark" to override it. Slot width is measured with ResizeObserver, so a narrow sidebar on a large monitor gets a compact layout.
The existing /api/v1/ads endpoint, house-ads.js SDK and loadHouseAds function remain supported aliases. New integrations should use the InfinitumAdsNetworkAPI names below.
Load the module once per page. Use your product slug in app so it cannot advertise itself. This working example is for InfiniView’s web app.
<script type="module" src="https://pittsburghsoftware.infinitumimagery.com/assets/InfinitumAdsNetworkAPI.js"></script>
<infinitum-ad app="infiniview" placement="auto" platform="auto"></infinitum-ad>
Use placement="card" for a compact recommendation, or banner for a wider slot. Both adapt to narrow screens. Omit platform or use auto to allow the detected device platform plus Web. Require a specific platform with iOS, Android, Web, macOS, Windows or visionOS to require that platform.
Use one non-obstructive placement per screen. Auto layout is the default. You may also request compact, or supply max-height="160" for a height-limited slot. The widget labels the promotion “From Infinitum · House ad,” includes a dismiss button and opens product details in a new tab only after a click. Inline ads never open overlays automatically. There is no auto-navigation or timed ad rotation.
The API placement names are banner, native-advanced, interstitial and app-open. Existing card, compact and automatic layouts remain supported. Campaigns must explicitly allow the requested placement. Automatic sizing never chooses a full-screen format.
<infinitum-ad app="infiniview" placement="native-advanced" platform="auto"></infinitum-ad>
For a custom Native Advanced view, select placement: 'native-advanced' and render the returned headline, body, imageUrl and cta as separate assets with the house-ad disclosure. These are your own house-ad formats, not Google Mobile Ads SDK objects.
import {InfinitumAdsNetworkAPI} from 'https://pittsburghsoftware.infinitumimagery.com/assets/InfinitumAdsNetworkAPI.js';
// Call after a completed activity or an explicit preview action.
await InfinitumAdsNetworkAPI.showFullscreen({
app: 'infiniview', format: 'interstitial', platform: 'auto'
});
// Alternatively, call from your app's welcome/loading flow:
// await InfinitumAdsNetworkAPI.showFullscreen({
// app: 'infiniview', format: 'app-open', platform: 'auto'
// });
showFullscreen resolves true when a displayed promotion closes, or false when no promotion can be shown. It allows one full-screen promotion at a time, supports immediate close and Escape, restores focus, and closes when the page becomes hidden or the creative expires. It does not register launch or foreground listeners. Your app decides when to call it; keep App Open to once per launch/return and avoid interrupting active work. Do not call it when returning from an ad link.
In Flutter, pass the same placement names into load. Use the returned assets in your own banner, native view or dismissible full-screen route. App Open lifecycle triggers, session frequency limits, safe areas, focus and expiry handling belong in your app; this Dart client selects an ad and does not display a native screen by itself.
GET https://pittsburghsoftware.infinitumimagery.com/api/v1/InfinitumAdsNetworkAPIThe equivalent /api/v1/InfinitumAdsNetworkAPI.json endpoint returns the same public snapshot. No API key, login, cookies or credentials are required. CORS allows cross-origin GET requests. Query parameters do not filter this static endpoint: selection happens in your application.
import {InfinitumAdsNetworkAPI} from 'https://pittsburghsoftware.infinitumimagery.com/assets/InfinitumAdsNetworkAPI.js';
try {
const feed = await InfinitumAdsNetworkAPI.load();
const ad = InfinitumAdsNetworkAPI.select(feed, {
app: 'infiniview', placement: 'card', platform: 'Web'
});
if (ad) {
console.log(ad.headline, ad.imageUrl, ad.destinationUrl);
}
} catch {
// Leave the ad slot empty; the app remains usable.
}
The module above is for browsers. Use InfinitumAdsNetworkAPI.detectPlatforms(navigator) to pass a platforms array to a custom selector, and resolveLayout(width, maxHeight) to choose a layout. For native apps, use the JSON API directly or the Flutter client below. Display the text as text, never as HTML. Open destinationUrl only when the user chooses the promotion.
| Field | Meaning |
|---|---|
data.name | InfinitumAdsNetworkAPI. Stable service name. |
schemaVersion | 1. Reject unsupported versions. |
generatedAt | UTC build time; not an impression timestamp. |
data.enabled | Global switch. False means display nothing. |
data.maxAgeSeconds | 300. Do not retain or display a fetched response beyond five minutes. |
data.disclosure | Visible house-ad label. |
data.campaigns | Eligible published creative pool; may be empty. |
campaign.id / product | Stable campaign ID and destination product slug. |
headline / body / cta | Plain-text creative and action label. |
imageUrl / destinationUrl | HTTPS image and publisher product-detail page. No redirects or tracking URLs. |
placements / platforms | Supported placement names and destination product platforms. |
variants / theme | Three creative versions and product color theme. The selector returns variant and themed creative text. |
category / tags | Public product topics used for local contextual matching. |
data.appCategories | Public product-slug to category mapping. |
weight | Base relative probability. Matching page/app category multiplies it by three. |
startsAt / endsAt | Nullable UTC ISO timestamps; start is inclusive, end is exclusive. |
includeApps / excludeApps | Contextual source-app slug lists. Empty includeApps allows every app; exclusions win. |
Filter by enabled state, placement, platform, campaign window and source-app rules. Always exclude campaign.product === app. Choose one remaining campaign using its relative weight. If none qualify, return no ad. These are display preferences, not authentication or permission rules.
Download the complete Dart client and add it to your app. It uses package:http, works with mobile and Flutter web, handles selection, and returns null on unavailable or malformed feeds. Add http and url_launcher to your app’s dependencies.
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'infinitum_house_ads.dart';
Future<InfinitumHouseAd?> loadPromotion() async {
final client = http.Client();
try {
return await InfinitumAdsNetworkAPI(client).load(
app: 'infiniview', platform: 'iOS', placement: 'card');
} finally {
client.close();
}
}
Future<void> openPromotion(InfinitumHouseAd ad) async {
if (DateTime.now().toUtc().isBefore(ad.expiresAt)) {
await launchUrl(Uri.parse(ad.destinationUrl),
mode: LaunchMode.externalApplication);
}
}
For Flutter, pass the available width from LayoutBuilder into load(width: constraints.maxWidth, placement: 'auto', ...). Use the returned ad.layout for your compact/card/banner view. Native sizing must be wired into that view; the client cannot resize your Flutter widgets by itself. Your native view must include the disclosure, allow dismissal, and hide the promotion when ad.expiresAt is reached or the app returns to the foreground after that time. Do not hold the result indefinitely. An Android app needs its normal Internet permission. Use the user’s current platform explicitly; do not infer a user identity.
Campaigns are controlled in this website project’s data/ads.json. Set the global enabled flag to false to stop all house ads, or set a campaign’s status to paused. Draft and paused creatives never enter the public feed. Only available, publicly listed products with an original icon can be advertised.
npm run ads:list
npm run ads:pause -- discover-frostfork
npm run ads:activate -- discover-frostfork
npm run deploy
Edit the headline, body, CTA, weight, app lists and UTC schedule in the campaign file, then deploy to publish the change. There is no public write API. This initial version is managed from the project files; it does not add a browser campaign editor. Deployment is required for pauses and edits. Allow up to five minutes for compliant clients to receive a changed feed; a currently visible web widget also expires within five minutes.
The feed is static and shared. App and platform selection stay on the device; the SDK does not send them to the server. Rotation remembers only product slugs and creative counters in sessionStorage on the current site/tab. This stays on the device and resets when the tab session ends; it is not sent to the API. If storage is unavailable, rotation uses page memory. There are no advertising IDs, analytics cookies, impression beacons, click counters or billing records. Ordinary hosting requests still reach Firebase and may be processed in its infrastructure logs. Destination products have their own policies.
Do not include user data in API URLs. On a network error, invalid response, expired cache or no match, show nothing. Do not let an ad request block your main screen. The website widget uses a six-second timeout and does not persist data in local storage. Campaigns are available without advertising charges; normal Hosting usage limits still apply.
If your host uses CSP, add the publisher origin below to its existing script-src, style-src, connect-src and img-src directives. Keep your existing sources. No inline-script or iframe permission is required.
https://pittsburghsoftware.infinitumimagery.com
You can also use https://infinitum-pittsburgh.web.app consistently for the SDK and endpoint. The widget loads its images, stylesheet and API from the origin serving the SDK. Hostnames must not be mixed in a restrictive CSP.