Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds AmpAdTemplate #16593

Merged
merged 39 commits into from Aug 28, 2018
Merged

Adds AmpAdTemplate #16593

merged 39 commits into from Aug 28, 2018

Conversation

glevitzky
Copy link
Contributor

@glevitzky glevitzky commented Jul 6, 2018

Adds feature that allows templatized ads to be fetched and rendered via Fast Fetch.

Sample implementation:

On the page:

<amp-ad type="test" width=320 height=50
  data-request-var-param1="val1"
  data-request-var-param2="val2"
  . . .
  data-request-var-paramn="valn"
  template>
</amp-ad>

Note that all attributes of the form data-request-var-<param_name>=<value> will be added to the request URL by appending&<param_name>=<value> to the registered URL (see below).

In amp-a4a/0.1/template-config.js:

export const NetworkRegistry = {
  // . . .
  myAdNetwork: {
    requestUrl: 'https://www.generic-ad-network.com?optionalStaticParam=foo',
  },
};

Some fields will automatically be substituted into the URL. Currently these are:

  • height
  • width

E.g., something like ...&sz=widthxheight will be expanded to ...&sz=320x50, if the size of the slot at request time is 320x50.

Addresses #15464.

.querySelector('template');
templateElement.parentNode
.replaceChild(renderedElement, templateElement);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍, my nits are fixed. Thanks!

@codecov-io
Copy link

codecov-io commented Jul 16, 2018

Codecov Report

Merging #16593 into master will increase coverage by 0.02%.
The diff coverage is 91.66%.

@@            Coverage Diff             @@
##           master   #16593      +/-   ##
==========================================
+ Coverage    77.9%   77.93%   +0.02%     
==========================================
  Files         562      564       +2     
  Lines       41131    41210      +79     
==========================================
+ Hits        32043    32115      +72     
- Misses       9088     9095       +7
Flag Coverage Δ
#integration_tests 36.12% <ø> (-0.06%) ⬇️
#unit_tests 76.99% <91.66%> (+0.03%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1e1828c...627c3b7. Read the comment docs.

@lannka
Copy link
Contributor

lannka commented Jul 23, 2018

High level:

  • I suggest to not have the template attribute. For real ad network integration, we should let the ad server decide what rendering method it wants.
  • How about type="custom-template" instead of type="test"
  • Nit: rename the attributes to data-request-param-abc-dce. Also convert the dash separated var name to camel case, as a convention in amp-analytis data-vars-*. (strings.js#dashToCamelCase)

@glevitzky
Copy link
Contributor Author

@lannka Thanks for the feedback.

  • If we do not use template attribute, how do we divert in amp-ad to use the correct constructor?
  • Easy enough.
  • Renamed to data-request-param.... Conversion to camel case happens automatically when reading element.dataset, but I've cleaned up the code around this a bit. Not sure how we should handle a case where pub wants a dash-separated param on request, but we can deal with that down the road.

@@ -22,27 +22,29 @@ import {getAmpAdTemplateHelper} from './template-validator';
*/
export class TemplateRenderer extends FriendlyFrameRenderer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general, inheritance like this is discouraged. Let's extract shared logic to a util method instead, and have TemplateRenderer extends Renderer . See here for more background around why.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of extending FriendlyFrameRenderer, can I keep an instance of it in TemplateRenderer? Since TemplateRenderer eventually renders into a friendly frame, it's unavoidable that I'll need the entirety of FriendlyFrameRenderer's logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

totally. i suggest convert FriendlyFrameRenderer into a util class without extending Renderer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I'd prefer to keep it as its own Renderer subclass, so its consistent and uniform with the other renderers. This will especially be useful once I finally get around to tackling the amp-a4a refactor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about a structure like:

TemplateRenderer -> Renderer
AmpRenderer (naming TBD) -> Renderer

Both renderer import the friendlyframeutil to share code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is that the util would just be the renderer itself, as there's little to nothing that would be left after extracting the common code. Can we circle back to this in a future PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having one renderer impl extend another renderer impl is the code pattern i want to avoid. Let's avoid at the beginning.

Given it's introduced in a previous PR, I'm OK to have this PR in first. But please do refactor in the next PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I completely agree with you on avoiding a TemplateRenderer -> FriendlyFrameRenderer -> Renderer hierarchy -- that's why I changed TemplateRenderer to use an instance of FriendlyFrameRenderer rather than extend it.

But, yes, we can do a refactor/cleanup after this PR. Meanwhile, feel free to start reviewing this.

export let NetworkRegistryDef;

/** @const {!NetworkRegistryDef} */
export const NetworkRegistry = {
Copy link
Contributor

@lannka lannka Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the default config for ad networks can be a feature added later. As I'm not yet sure that it will be that helpful.

This amp-ad-custom extension is mainly for demo or trial purpose. Any real ad network should consider have its own extension amp-ad-network-a.

let url = this.baseRequestUrl_;

// We collect all fields in the dataset of the form
// 'data-request-var-<field_name>=<val>`, and append &<field_name>=<val> to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update doc here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}
});
this.getContext().adUrl = url;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it needed right now?

I want to make sure we only add necessary stuff into the context object. And I wish we can later document clearly what the context object contains.

Can you check all the other context data, and remove the ones are not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is used by friendly-frame-renderer.js on line 97, though I'm not certain how necessary that is.

* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {AmpAdTemplate} from '../../amp-a4a/0.1/amp-ad-template';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we just move AmpAdTemplate here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean move the whole module into this file, or just move the module into this extension?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whole module to this file. basically merge the 2 files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -933,6 +933,7 @@ app.get('/adzerk/*', (req, res) => {
fs.readFileAsync(filePath).then(file => {
res.setHeader('Content-Type', 'application/json');
res.setHeader('AMP-template-amp-creative', 'amp-mustache');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we already changed to
AMP-Ad-Template-Extension: amp-mustache

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did, but I must've forgotten to change it here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and you can remove this line now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@glevitzky glevitzky force-pushed the templateads branch 2 times, most recently from 1f4b820 to 9df7385 Compare August 17, 2018 18:48
@ghost
Copy link

ghost commented Aug 17, 2018

This pull request introduces 1 alert when merging 4c0365c into cb7e267 - view on LGTM.com

new alerts:

  • 1 for Syntax error

Comment posted by LGTM.com

@@ -933,6 +933,7 @@ app.get('/adzerk/*', (req, res) => {
fs.readFileAsync(filePath).then(file => {
res.setHeader('Content-Type', 'application/json');
res.setHeader('AMP-template-amp-creative', 'amp-mustache');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and you can remove this line now

(headers.get(AMP_TEMPLATED_CREATIVE_HEADER_NAME) !== 'amp-mustache' &&
headers.get(DEPRECATED_AMP_TEMPLATED_CREATIVE_HEADER_NAME) !==
'amp-mustache')) {
return Promise.resolve(
/** @type {!./amp-ad-type-defs.ValidatorOutput} */ ({
creativeData: {
creative: body,
crossDomainData: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand why this extra layer is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't recall if I had a reason or not. So far seems to work fine without it, so I've removed it.

import {getAmpAdTemplateHelper} from './template-validator';

/**
* Render AMP creative into FriendlyFrame via templatization.
*/
export class TemplateRenderer extends FriendlyFrameRenderer {
export class TemplateRenderer extends Renderer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is good. now we also need to change FriendlyFrameRender to a helper util class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return Promise.resolve();
}
const templateHelper = getAmpAdTemplateHelper(context.win);
const {iframe} = this.friendlyFrameRenderer_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once you made friendlyFrameRenderer an util class, then its render() can return this iframe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@lannka lannka merged commit c76afea into ampproject:master Aug 28, 2018
Enriqe pushed a commit to Enriqe/amphtml that referenced this pull request Nov 28, 2018
* init

* Tests + more.

* Lint + types

* First test now passing.

* More tests.

* Removing erronesouly added file.

* Inserting element rather than overriding innerHTML.

* Another erroneously added file.

* Added amp-template-ad

* Basic functionality in place.

* Reseting yarn.lock

* Lint.

* Fixed tests + types.

* Lint

* Added test-amp-ad-template.js + dep-check fix.

* Merges.

* Using replaceChild + parent of templateElement rather than body.

* Added NameFrameRenderer as non-AMP rendering mode + additional test.

* Added URL expansion.

* More tests.

* Added amp-ad test + fixed template-validator test.

* Cleaning up added element in test-tempate-renderer.

* Restructring how query params are added to request.

* Minor feedback changes.

* Added amp-ad-custom extension.

* Restoring to previous commit.

* Fixing template-renderer.

* Removing amp-ad changes.

* Things back in functional state.

* Moving amp-ad-template to amp-ad-custom.

* Fixed accidentally reverted header.

* Factored out friendly-frame-util + minor fixes.

* Adding test to ff util.

* XHR type decl fix.

* One more XHR type decl fix.

* One more XHR type decl fix.

* Minor type + dep fixes.

* Test fix.

* Test fix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants