adstream
v1.0.49
Published
Add a stream of ads with Add-Stream.
Maintainers
Readme
AdStream
Add-Stream is a lightweight, flexible ad-streaming solution, It supports seamless integration across React, Next.js, HTML, Web Components, and mobile WebViews (Flutter, iOS, Android).
✨ Features
- ✔ Display Responsive ad by zone ID
- ✔ Custom loader and error fallback
- ✔ Can be used in plain HTML via Web Components
- ✔ Can be embedded in
Flutterusing WebView
🚀 Installation
npm install adstream
# or
yarn add adstream📦 Usage
import React from "react";
import { AdStream } from "adstream";
function App() {
return <AdStream zoneId={200} />;
}
export default App;All props example
import React from "react";
import { AdStream } from "adstream";
function App() {
return (
<AdStream
zoneId={200}
height={{ xs: 200, md: 300, lg: 400, xl: 500 }}
width="100%"
aspectRatio="4 / 3"
boxShadow={4}
sx={{ borderRadius: 12, backgroundColor: "#fafafa" }}
loader={<div>Loading single ad...</div>}
errorText={<div>Oops! Could not load the ad.</div>}
/>
);
}
export default App;Integration with Next.js, both for:
✅ Pages Router (with SSR-safe dynamic import)
Use next/dynamic to safely render AdStream client-side only:
// components/SafeAdStreamWrapper.tsx
import React from "react";
import { AdStream } from "adstream";
const SafeAdStreamWrapper = () => {
return (
<AdStream
zoneId={200}
height={{ xs: 200, md: 336 }}
aspectRatio="16 / 9"
boxShadow={2}
sx={{ borderRadius: 0 }}
width="100%"
/>
);
};
export default SafeAdStreamWrapper;
// Then import it dynamically in your page:
// pages/index.tsx or any route
import dynamic from "next/dynamic";
const SafeAdStream = dynamic(
() => import("../components/SafeAdStreamWrapper"),
{
ssr: false,
loading: () => <div>Loading ads...</div>,
}
);
export default function HomePage() {
return (
<div>
<h2>Dashboard</h2>
<SafeAdStream />
</div>
);
}✅ App Router (/app/page.tsx)
With App Router, make sure to mark the component with "use client" and import AdStream normally:
// app/demo/page.tsx
"use client";
import { AdStream } from "adstream";
import { Stack } from "@mui/material";
export default function Demo() {
return (
<Stack spacing={2} maxWidth={600} margin="0 auto">
<AdStream
zoneId={200}
aspectRatio="16 / 9"
boxShadow={3}
width="100%"
height={{ xs: 200, md: 300 }}
/>
</Stack>
);
}🎛️ Customization
AdStream Props
| Prop | Type | Description | |
| ------------- | ---------------- | -------------------------------------- | ------------------------- |
| zoneId | number | The ad zone ID | |
| loader | ReactNode | Optional loader fallback | |
| height | `number | object` | Responsive height |
| width | `number | string` | Width of the ad component |
| aspectRatio | string | CSS aspect ratio for responsive layout | |
| boxShadow | number | MUI shadow level | |
| sx | SxProps<Theme> | Additional style overrides | |
| errorText | ReactNode | Error message if ad fails to load | |
🌐 Using in Plain HTML via Web Components
You can use adstream in any HTML file by loading the built-in Web Component.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Ad Stream Demo</title>
</head>
<body>
<script src="https://unpkg.com/adstream/dist/browser/web-component.global.js"></script>
<div style="max-width: 600px; margin: 0 auto">
<ad-stream
zoneid="18"
aspectratio="16 / 9"
height='{"xs": 200, "md": 300}'
width="100%"
sx='{"borderRadius": 1}'
></ad-stream>
<script>
const adStream = document.querySelector("ad-stream");
setTimeout(() => {
adStream.setAdstreamKey("YOUR_ADSTREAM_KEY");
}, 100);
</script>
</div>
</body>
</html>📱 Use with Flutter WebView
AdStream Web Components work in any mobile app that can render HTML — including Flutter apps using a WebView.
✅ Example using webview_flutter
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
import 'package:url_launcher/url_launcher.dart';
/// A highly customizable ad banner component using AdStream technology
/// Features:
/// - Responsive ad container
/// - Memory-efficient WebView management
/// - External link handling
class AdStreamBanner extends StatefulWidget {
final int? zoneId;
final int zoneWidth;
final int zoneHeight;
const AdStreamBanner({
super.key,
this.zoneId,
required this.zoneWidth,
required this.zoneHeight,
});
@override
State<AdStreamBanner> createState() => _AdStreamBannerState();
}
class _AdStreamBannerState extends State<AdStreamBanner> {
late WebViewController controller;
@override
void dispose() {
controller.clearCache();
super.dispose();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_initializeController();
}
/// Generates the HTML content for the ad banner
getAdHtml() {
String html = '''
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/adstream/dist/browser/web-component.global.js"></script>
<style>
html, body {
margin: 0;
padding: 0;
background: #ffffff;
height: 100%;
}
</style>
</head>
<body>
<ad-stream
zoneid="${widget.zoneId}"
aspectratio="16 / 9"
height='{"xs": ${_calculateHeight()}, "md": ${_calculateHeight()}}'
width="100%"
sx='{"borderRadius": 1}'
></ad-stream>
<script>
const addstream = document.querySelector("ad-stream");
setTimeout(() => {
addstream.setAdstreamKey("YOUR_ADSTREAM_KEY");
}, 100);
</script>
</body>
</html>
''';
return html;
}
void _initializeController() {
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.white)
..addJavaScriptChannel(
'ExternalLink',
onMessageReceived: (JavaScriptMessage message) {
_launchExternalUrl(message.message);
},
)
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith("http")) {
_launchExternalUrl(request.url);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onWebResourceError: (WebResourceError error) {},
),
)
..loadHtmlString(getAdHtml());
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: _calculateHeight(),
child: WebViewWidget(
controller: controller,
),
);
}
double _calculateHeight() {
final screenWidth = MediaQuery.of(context).size.width;
final aspectRatio = widget.zoneWidth / widget.zoneHeight;
double calculatedHeight = screenWidth / aspectRatio;
return calculatedHeight.clamp(50.0, 300.0);
}
Future<void> _launchExternalUrl(String url) async {
final uri = Uri.tryParse(url);
if (uri != null && await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
} else {
debugPrint("❌ Could not launch $url");
}
}
}✅ This can be used in both Android and iOS. Just be sure you:
- Enable JavaScript
- Set proper height on the WebView
