Commit ae8b9c57 authored by isstuev's avatar isstuev

ad banners

parent 945042fa
...@@ -37,6 +37,8 @@ NEXT_PUBLIC_HOMEPAGE_CHARTS=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_CHARTS__ ...@@ -37,6 +37,8 @@ NEXT_PUBLIC_HOMEPAGE_CHARTS=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_CHARTS__
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT__ NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT__
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER__ NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER__
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME__ NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME__
NEXT_PUBLIC_AD_DOMAIN_WITH_AD=__PLACEHOLDER_FOR_NEXT_PUBLIC_DOMAIN_WITH_AD__
NEXT_PUBLIC_AD_ADBUTLER_ON=__PLACEHOLDER_FORNEXT_PUBLIC_AD_ADBUTLER_ON__
# api config # api config
NEXT_PUBLIC_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_HOST__ NEXT_PUBLIC_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_HOST__
......
...@@ -76,7 +76,8 @@ The app instance could be customized by passing following variables to NodeJS en ...@@ -76,7 +76,8 @@ The app instance could be customized by passing following variables to NodeJS en
| NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT | `string` *(optional)* | Gradient value for hero plate on the homepage | `radial-gradient(at 15% 86%, hsla(350,65%,70%,1) 0px, transparent 50%), radial-gradient(at 72% 57%, hsla(14,95%,76%,1) 0px, transparent 50%)` | | NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT | `string` *(optional)* | Gradient value for hero plate on the homepage | `radial-gradient(at 15% 86%, hsla(350,65%,70%,1) 0px, transparent 50%), radial-gradient(at 72% 57%, hsla(14,95%,76%,1) 0px, transparent 50%)` |
| NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER | `boolean` *(optional)* | Set to false if network doesn't have gas tracker | `true` | | NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER | `boolean` *(optional)* | Set to false if network doesn't have gas tracker | `true` |
| NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` *(optional)* | Set to false if average block time is useless for the network | `true` | | NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` *(optional)* | Set to false if average block time is useless for the network | `true` |
| NEXT_PUBLIC_DOMAIN_WITH_AD | `string` *(optional)* | The domain on which we display ads | `blockscout.com` |
| NEXT_PUBLIC_AD_ADBUTLER_ON | `boolean` *(optional)* | Set to true to show Adbutler banner instead of Coinzilla banner | `false` |
### App configuration ### App configuration
| Variable | Type | Description | Default value | Variable | Type | Description | Default value
......
...@@ -85,6 +85,10 @@ const config = Object.freeze({ ...@@ -85,6 +85,10 @@ const config = Object.freeze({
baseUrl, baseUrl,
authUrl, authUrl,
logoutUrl, logoutUrl,
ad: {
domainWithAd: getEnvValue(process.env.NEXT_PUBLIC_AD_DOMAIN_WITH_AD) || 'blockscout.com',
adButlerOn: getEnvValue(process.env.NEXT_PUBLIC_AD_ADBUTLER_ON) === 'true',
},
api: { api: {
endpoint: apiHost ? `https://${ apiHost }` : 'https://blockscout.com', endpoint: apiHost ? `https://${ apiHost }` : 'https://blockscout.com',
socket: apiHost ? `wss://${ apiHost }` : 'wss://blockscout.com', socket: apiHost ? `wss://${ apiHost }` : 'wss://blockscout.com',
......
import appConfig from 'configs/app/config';
export default function isSelfHosted() {
return appConfig.host?.endsWith(appConfig.ad.domainWithAd) || appConfig.host === 'localhost';
}
export default async function insertAdText() {
const ad = document.getElementsByClassName('coinzilla');
ad[0].textContent = 'coinzilla banner!';
}
...@@ -5,6 +5,7 @@ import * as blockMock from 'mocks/blocks/block'; ...@@ -5,6 +5,7 @@ import * as blockMock from 'mocks/blocks/block';
import * as dailyTxsMock from 'mocks/stats/daily_txs'; import * as dailyTxsMock from 'mocks/stats/daily_txs';
import * as statsMock from 'mocks/stats/index'; import * as statsMock from 'mocks/stats/index';
import * as txMock from 'mocks/txs/tx'; import * as txMock from 'mocks/txs/tx';
import insertAdText from 'playwright/scripts/insertAdText';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import Home from './Home'; import Home from './Home';
...@@ -40,5 +41,7 @@ test('default view -@default +@desktop-xl +@mobile +@dark-mode', async({ mount, ...@@ -40,5 +41,7 @@ test('default view -@default +@desktop-xl +@mobile +@dark-mode', async({ mount,
</TestApp>, </TestApp>,
); );
await page.evaluate(insertAdText);
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
...@@ -6,6 +6,7 @@ import ChainIndicators from 'ui/home/indicators/ChainIndicators'; ...@@ -6,6 +6,7 @@ import ChainIndicators from 'ui/home/indicators/ChainIndicators';
import LatestBlocks from 'ui/home/LatestBlocks'; import LatestBlocks from 'ui/home/LatestBlocks';
import LatestTxs from 'ui/home/LatestTxs'; import LatestTxs from 'ui/home/LatestTxs';
import Stats from 'ui/home/Stats'; import Stats from 'ui/home/Stats';
import AdBanner from 'ui/shared/ad/AdBanner';
import Page from 'ui/shared/Page/Page'; import Page from 'ui/shared/Page/Page';
import ColorModeToggler from 'ui/snippets/header/ColorModeToggler'; import ColorModeToggler from 'ui/snippets/header/ColorModeToggler';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop'; import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
...@@ -47,6 +48,7 @@ const Home = () => { ...@@ -47,6 +48,7 @@ const Home = () => {
</Box> </Box>
<Stats/> <Stats/>
<ChainIndicators/> <ChainIndicators/>
<AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/>
<Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }> <Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }>
<LatestBlocks/> <LatestBlocks/>
<LatestTxs/> <LatestTxs/>
......
...@@ -11,6 +11,7 @@ import { useAppContext } from 'lib/appContext'; ...@@ -11,6 +11,7 @@ import { useAppContext } from 'lib/appContext';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
import isBrowser from 'lib/isBrowser'; import isBrowser from 'lib/isBrowser';
import networkExplorers from 'lib/networks/networkExplorers'; import networkExplorers from 'lib/networks/networkExplorers';
import AdBanner from 'ui/shared/ad/AdBanner';
import ExternalLink from 'ui/shared/ExternalLink'; import ExternalLink from 'ui/shared/ExternalLink';
import Page from 'ui/shared/Page/Page'; import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
...@@ -83,6 +84,7 @@ const TransactionPageContent = () => { ...@@ -83,6 +84,7 @@ const TransactionPageContent = () => {
) } ) }
</Flex> </Flex>
<RoutedTabs tabs={ TABS }/> <RoutedTabs tabs={ TABS }/>
<AdBanner mt={ 6 } justifyContent={{ base: 'center', lg: 'start' }}/>
</Page> </Page>
); );
}; };
......
import { chakra } from '@chakra-ui/react';
import React from 'react';
import appConfig from 'configs/app/config';
import isSelfHosted from 'lib/isSelfHosted';
import AdbutlerBanner from './AdbutlerBanner';
import CoinzillaBanner from './CoinzillaBanner';
const AdBanner = ({ className }: { className?: string }) => {
if (!isSelfHosted()) {
return null;
}
if (appConfig.ad.adButlerOn) {
return <AdbutlerBanner className={ className }/>;
}
return <CoinzillaBanner className={ className }/>;
};
export default chakra(AdBanner);
/* eslint-disable max-len */
import { Flex, chakra } from '@chakra-ui/react';
import React from 'react';
// eslint-disable-next-line @typescript-eslint/no-var-requires
// const adbutlerHTML = require('ui/shared/ad/adbutler.html');
// didn't find a way to raw-load html that works both for webpack (app build) and vite (playwright build)
const adbutlerHTML = `
<div id="ad-banner"></div>
<script type="text/javascript">if (!window.AdButler){(function(){var s = document.createElement("script"); s.async = true; s.type = "text/javascript";s.src = 'https://servedbyadbutler.com/app.js';var n = document.getElementsByTagName("script")[0]; n.parentNode.insertBefore(s, n);}());}</script>
<script type="text/javascript">
var AdButler = AdButler || {}; AdButler.ads = AdButler.ads || [];
var abkw = window.abkw || '';
const isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
if (isMobile) {
var plc539876 = window.plc539876 || 0;
document.getElementById('ad-banner').innerHTML += '<'+'div id="placement_539876_'+plc539876+'"></'+'div>';
document.getElementById("ad-banner").className = "ad-container mb-3";
AdButler.ads.push({handler: function(opt){ AdButler.register(182226, 539876, [320,100], 'placement_539876_'+opt.place, opt); }, opt: { place: plc539876++, keywords: abkw, domain: 'servedbyadbutler.com', click:'CLICK_MACRO_PLACEHOLDER' }});
} else {
var plc523705 = window.plc523705 || 0;
document.getElementById('ad-banner').innerHTML += '<'+'div id="placement_523705_'+plc523705+'"></'+'div>';
AdButler.ads.push({handler: function(opt){ AdButler.register(182226, 523705, [728,90], 'placement_523705_'+opt.place, opt); }, opt: { place: plc523705++, keywords: abkw, domain: 'servedbyadbutler.com', click:'CLICK_MACRO_PLACEHOLDER' }});
}
</script>
`;
const AdbutlerBanner = ({ className }: { className?: string }) => {
return (
<Flex className={ className } dangerouslySetInnerHTML={{ __html: adbutlerHTML }}/>
);
};
export default chakra(AdbutlerBanner);
import { Flex, chakra } from '@chakra-ui/react';
import React from 'react';
import isBrowser from 'lib/isBrowser';
declare global {
interface Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
coinzilla_display: any;
}
}
type CPreferences = {
zone: string;
width: string;
height: string;
}
const CoinzillaBanner = ({ className }: { className?: string }) => {
const isInBrowser = isBrowser();
if (isInBrowser) {
window.coinzilla_display = window.coinzilla_display || [];
const cDisplayPreferences = {} as CPreferences;
cDisplayPreferences.zone = '26660bf627543e46851';
cDisplayPreferences.width = '728';
cDisplayPreferences.height = '90';
window.coinzilla_display.push(cDisplayPreferences);
}
return (
<Flex className={ className }>
<script async src="https://coinzillatag.com/lib/display.js"></script>
<div className="coinzilla" data-zone="C-26660bf627543e46851"></div>
</Flex>
);
};
export default chakra(CoinzillaBanner);
<div id="ad-banner"></div>
<script type="text/javascript">if (!window.AdButler){(function(){var s = document.createElement("script"); s.async = true; s.type = "text/javascript";s.src = 'https://servedbyadbutler.com/app.js';var n = document.getElementsByTagName("script")[0]; n.parentNode.insertBefore(s, n);}());}</script>
<script type="text/javascript">
var AdButler = AdButler || {}; AdButler.ads = AdButler.ads || [];
var abkw = window.abkw || '';
const isMobile = window.matchMedia("only screen and (max-width: 760px)").matches;
if (isMobile) {
var plc539876 = window.plc539876 || 0;
document.getElementById('ad-banner').innerHTML += '<'+'div id="placement_539876_'+plc539876+'"></'+'div>';
document.getElementById("ad-banner").className = "ad-container mb-3";
AdButler.ads.push({handler: function(opt){ AdButler.register(182226, 539876, [320,100], 'placement_539876_'+opt.place, opt); }, opt: { place: plc539876++, keywords: abkw, domain: 'servedbyadbutler.com', click:'CLICK_MACRO_PLACEHOLDER' }});
} else {
var plc523705 = window.plc523705 || 0;
document.getElementById('ad-banner').innerHTML += '<'+'div id="placement_523705_'+plc523705+'"></'+'div>';
AdButler.ads.push({handler: function(opt){ AdButler.register(182226, 523705, [728,90], 'placement_523705_'+opt.place, opt); }, opt: { place: plc523705++, keywords: abkw, domain: 'servedbyadbutler.com', click:'CLICK_MACRO_PLACEHOLDER' }});
}
</script>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment