diff --git a/clients/web/src/components/content-ads/content-ads.js b/clients/web/src/components/content-ads/content-ads.js index 06f42d21d..2dd4ffd33 100644 --- a/clients/web/src/components/content-ads/content-ads.js +++ b/clients/web/src/components/content-ads/content-ads.js @@ -1,5 +1,7 @@ import { css } from '@emotion/css' -import { AdSlot } from 'components/programmatic-ad/freestar-ad-slot' +import { AdSlot } from 'components/programmatic-ad/mozads-ad-slot' + +import { IABFixedSize } from '@mozilla-services/ads-sdk/dist/core' const aboveTheFoldStyle = css` margin-bottom: var(--spacing250); @@ -17,26 +19,61 @@ const adRailStyle = css` const belowTheFoldStyle = css` margin-top: 4rem; ` -// Syndicated Article Freestar placement IDs -const ABOVE_THE_FOLD = 'getpocket_leaderboard_atf' -const BELOW_THE_FOLD = 'getpocket_leaderboard_btf' -const RIGHT_RAIL_1_ID = 'getpocket_right_rail_1' -const RIGHT_RAIL_2_ID = 'getpocket_right_rail_2' -export function AdAboveTheFold({ allowAds, targeting }) { +// Syndicated Article MozAds placements +const ABOVE_THE_FOLD_MARS_ID = "pocket_billboard_1" +const BELOW_THE_FOLD_MARS_ID = "pocket_billboard_2" +const ABOVE_THE_FOLD_MOBILE_MARS_ID = "pocket_mrec_1" +const BELOW_THE_FOLD_MOBILE_MARS_ID = "pocket_mrec_2" +const RIGHT_RAIL_1_MARS_ID = "pocket_skyscraper_1" +const RIGHT_RAIL_2_MARS_ID = "pocket_skyscraper_2" + +let placements = {} +placements[ABOVE_THE_FOLD_MARS_ID] = IABFixedSize.Billboard, +placements[BELOW_THE_FOLD_MARS_ID] = IABFixedSize.Billboard, +placements[ABOVE_THE_FOLD_MOBILE_MARS_ID] = IABFixedSize.MediumRectangle +placements[BELOW_THE_FOLD_MOBILE_MARS_ID] = IABFixedSize.MediumRectangle +placements[RIGHT_RAIL_1_MARS_ID] = IABFixedSize.Skyscaper, +placements[RIGHT_RAIL_2_MARS_ID] = IABFixedSize.Skyscaper + +export function BillboardAboveTheFold({ allowAds, targeting }) { + return allowAds ? ( + + ) : null +} + +export function BillboardBelowTheFold({ allowAds, targeting }) { + return allowAds ? ( + + ) : null +} + +export function RectangleAboveTheFold({ allowAds, targeting }) { return allowAds ? ( ) : null } -export function AdBelowTheFold({ allowAds, targeting }) { +export function RectangleBelowTheFold({ allowAds, targeting }) { return allowAds ? ( @@ -46,7 +83,10 @@ export function AdBelowTheFold({ allowAds, targeting }) { export function AdRailTop({ allowAds, targeting }) { return allowAds ? (
- +
) : null } @@ -54,7 +94,10 @@ export function AdRailTop({ allowAds, targeting }) { export function AdRailBottom({ allowAds, targeting }) { return allowAds ? (
- +
) : null } diff --git a/clients/web/src/components/programmatic-ad/mozads-ad-slot.js b/clients/web/src/components/programmatic-ad/mozads-ad-slot.js new file mode 100644 index 000000000..fc916470c --- /dev/null +++ b/clients/web/src/components/programmatic-ad/mozads-ad-slot.js @@ -0,0 +1,47 @@ +import PropTypes from 'prop-types' +import { css } from '@emotion/css' +import { useTranslation } from 'next-i18next' + +import { MozAdsPlacement } from '@mozilla-services/ads-sdk/dist/react' + +const programmaticAdWrapperStyles = css` + display: flex; + flex-direction: column; + align-items: center; + + .label { + font-family: var(--fontSansSerif); + font-size: 0.85rem; + line-height: 100%; + color: var(--color-textTertiary); + text-align: center; + margin: 0; + padding-bottom: 0.5rem; + width: 100%; + } +` + +export function AdSlot({ placementId, placementName, targeting, instanceStyles }) { + const { t } = useTranslation() + const adLabel = t('ad:label', 'Advertisement') + + return ( +
+ +

{adLabel}

+
+ ) +} + +AdSlot.propTypes = { + // A string of the ad unit placement, which are constants provided by ads-sdk + placementName: PropTypes.string.isRequired, + // An *optional* object of key/value pairs for targeting. + targeting: PropTypes.object, + // An *optional* classname to add to the ad container + instanceStyles: PropTypes.string +} diff --git a/clients/web/src/containers/syndicated-article/syndicated-article.js b/clients/web/src/containers/syndicated-article/syndicated-article.js index 2b947847c..51bec3b2e 100644 --- a/clients/web/src/containers/syndicated-article/syndicated-article.js +++ b/clients/web/src/containers/syndicated-article/syndicated-article.js @@ -16,8 +16,10 @@ import { ArticleActions } from 'components/content-actions/article-actions' import { SaveArticleTop } from 'components/content-saving/save-article' import { SaveArticleBottom } from 'components/content-saving/save-article' -import { AdAboveTheFold } from 'components/content-ads/content-ads' -import { AdBelowTheFold } from 'components/content-ads/content-ads' +import { BillboardAboveTheFold } from 'components/content-ads/content-ads' +import { BillboardBelowTheFold } from 'components/content-ads/content-ads' +import { RectangleAboveTheFold } from 'components/content-ads/content-ads' +import { RectangleBelowTheFold } from 'components/content-ads/content-ads' import { AdRailTop } from 'components/content-ads/content-ads' import { AdRailBottom } from 'components/content-ads/content-ads' @@ -139,6 +141,10 @@ export function SyndicatedArticle({ queryParams = validParams, locale }) { const syndicatedFrom = publisherUrl ? publisherUrl : false const ArticleLayout = isMobileWebView ? MobileLayout : Layout + // Prepare the correct ad format for the viewport size + const AdAboveTheFold = isMobileWebView ? RectangleAboveTheFold : BillboardAboveTheFold + const AdBelowTheFold = isMobileWebView ? RectangleBelowTheFold : BillboardBelowTheFold + // Prep save action const onSave = (url, value) => { dispatch(sendSnowplowEvent('syndicated.article.save', { url, value }))